前两篇简单谈了一些.Net Core的优势以及机构设计的一些思路,这一篇开始,我们将从零开始搭建架构,底层我们将采用EF来访问数据库,所以这篇我们将贴一下EF常用操作的基类。

框架搭建与EF常用基类实现-LMLPHP

简单介绍下一些类库将要实现的功能:

Business:业务实现层

Domains:实体(Model)

Service:接口

Data:数据库访问(EF或其他)

EasyCacheing:开源缓存管理

Tools:工具类库

其他的我们用到的时候再说;

接着说EF常用操作基类,我们将基类放在Data下,具体目录结构如下:

框架搭建与EF常用基类实现-LMLPHP

BaseEntity:实体基类,基础共有的放在这里面:

 using System;
using System.Collections.Generic;
using System.Text; namespace Data
{
/// <summary>
/// Base class for entities
/// </summary>
///[Serializable]
public abstract partial class BaseEntity
{
/// <summary>
/// Gets or sets the entity identifier
/// </summary>
public string Id { get; set; }
public virtual Nullable<DateTime> CreateTime { get; set; }
public virtual string CreatePerson { get; set; }
public virtual Nullable<DateTime> UpdateTime { get; set; }
public virtual string UpdatePerson { get; set; } public BaseEntity()
{
this.Id = GetIdentifier();
this.CreateTime = DateTime.Now;
this.UpdateTime = DateTime.Now;
} private string GetIdentifier()
{
return Guid.NewGuid().ToString();
} public override bool Equals(object obj)
{
return Equals(obj as BaseEntity);
} private static bool IsTransient(BaseEntity obj)
{
return obj != null && Equals(obj.Id, default(string));
} private Type GetUnproxiedType()
{
return GetType();
} public virtual bool Equals(BaseEntity other)
{
if (other == null)
return false; if (ReferenceEquals(this, other))
return true; if (!IsTransient(this) &&
!IsTransient(other) &&
Equals(Id, other.Id))
{
var otherType = other.GetUnproxiedType();
var thisType = GetUnproxiedType();
return thisType.IsAssignableFrom(otherType) ||
otherType.IsAssignableFrom(thisType);
} return false;
} public static bool operator ==(BaseEntity x, BaseEntity y)
{
return Equals(x, y);
} public static bool operator !=(BaseEntity x, BaseEntity y)
{
return !(x == y);
}
}
}

DbContextExtensions:数据库操作扩展

 using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlClient;
using System.Reflection;
using System.Text; namespace Data
{
public static class DbContextExtensions
{
private static void CombineParams(ref DbCommand command, params object[] parameters)
{
if (parameters != null)
{
foreach (SqlParameter parameter in parameters)
{
if (!parameter.ParameterName.Contains("@"))
parameter.ParameterName = $"@{parameter.ParameterName}";
command.Parameters.Add(parameter);
}
}
} private static DbCommand CreateCommand(DatabaseFacade facade, string sql, out DbConnection dbConn, params object[] parameters)
{
DbConnection conn = facade.GetDbConnection();
dbConn = conn;
conn.Open();
DbCommand cmd = conn.CreateCommand();
if (facade.IsSqlServer())
{
cmd.CommandText = sql;
CombineParams(ref cmd, parameters);
}
return cmd;
} public static DataTable SqlQuery(this DatabaseFacade facade, string sql, params object[] parameters)
{
DbCommand cmd = CreateCommand(facade, sql, out DbConnection conn, parameters);
DbDataReader reader = cmd.ExecuteReader();
DataTable dt = new DataTable();
dt.Load(reader);
reader.Close();
conn.Close();
return dt;
} public static IEnumerable<T> SqlQuery<T>(this DatabaseFacade facade, string sql, params object[] parameters) where T : class, new()
{
DataTable dt = SqlQuery(facade, sql, parameters);
return dt.ToEnumerable<T>();
} public static IEnumerable<T> ToEnumerable<T>(this DataTable dt) where T : class, new()
{
PropertyInfo[] propertyInfos = typeof(T).GetProperties();
T[] ts = new T[dt.Rows.Count];
int i = ;
foreach (DataRow row in dt.Rows)
{
T t = new T();
foreach (PropertyInfo p in propertyInfos)
{
if (dt.Columns.IndexOf(p.Name) != - && row[p.Name] != DBNull.Value)
p.SetValue(t, row[p.Name], null);
}
ts[i] = t;
i++;
}
return ts;
}
}
}

IPagedList:分页接口

 using System;
using System.Collections.Generic;
using System.Text; namespace Data
{
public interface IPagedList<T> : IList<T>
{
int PageIndex { get; }
int PageSize { get; }
int TotalCount { get; }
int TotalPages { get; }
bool HasPreviousPage { get; }
bool HasNextPage { get; }
}
}

PagedList:分页接口的实现

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text; namespace Data
{
/// <summary>
/// Paged list
/// </summary>
/// <typeparam name="T">T</typeparam>
public class PagedList<T> : List<T>, IPagedList<T>
{
/// <summary>
/// Ctor
/// </summary>
/// <param name="source">source</param>
/// <param name="pageIndex">Page index</param>
/// <param name="pageSize">Page size</param>
public PagedList(IQueryable<T> source, int pageIndex, int pageSize)
{
int total = source.Count();
this.TotalCount = total;
this.TotalPages = total / pageSize; if (total % pageSize > )
TotalPages++; this.PageSize = pageSize;
this.PageIndex = pageIndex;
this.AddRange(source.Skip((pageIndex - ) * pageSize).Take(pageSize).ToList());
} /// <summary>
/// Ctor
/// </summary>
/// <param name="source">source</param>
/// <param name="pageIndex">Page index</param>
/// <param name="pageSize">Page size</param>
public PagedList(IList<T> source, int pageIndex, int pageSize)
{
TotalCount = source.Count();
TotalPages = TotalCount / pageSize; if (TotalCount % pageSize > )
TotalPages++; this.PageSize = pageSize;
this.PageIndex = pageIndex;
this.AddRange(source.Skip((pageIndex - ) * pageSize).Take(pageSize).ToList());
} /// <summary>
/// Ctor
/// </summary>
/// <param name="source">source</param>
/// <param name="pageIndex">Page index</param>
/// <param name="pageSize">Page size</param>
/// <param name="totalCount">Total count</param>
public PagedList(IEnumerable<T> source, int pageIndex, int pageSize, int totalCount)
{
TotalCount = totalCount;
TotalPages = TotalCount / pageSize; if (TotalCount % pageSize > )
TotalPages++; this.PageSize = pageSize;
this.PageIndex = pageIndex;
this.AddRange(source);
} public int PageIndex { get; private set; }
public int PageSize { get; private set; }
public int TotalCount { get; private set; }
public int TotalPages { get; private set; } public bool HasPreviousPage
{
get { return (PageIndex > ); }
}
public bool HasNextPage
{
get { return (PageIndex + < TotalPages); }
}
}
}

IEnumerableExtensions:IEnumerable分页的扩展

 using System.Collections.Generic;
using System.Linq; namespace Data
{
public static class IEnumerableExtensions
{
public static PagedList<TSource> ToPageList<TSource>(this IEnumerable<TSource> source, int pageIndex, int pageSize)
{
if (pageIndex < )
pageIndex = ;
int TotalCount = ;
List<TSource> resultList = new List<TSource>();
resultList = source.Skip((pageIndex - ) * pageSize).Take(pageSize).ToList(); ;
TotalCount = source.Count();
return new PagedList<TSource>(resultList, pageIndex, pageSize, TotalCount);
}
}
}

IRepository:数据库仓库访问接口

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions; namespace Data
{
public interface IRepository<T> where T : BaseEntity
{
/// <summary>
/// 通过ID获取单个实体
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
T GetById(object id);
/// <summary>
/// 插入单个实体
/// </summary>
/// <param name="entity">实体</param>
/// <returns></returns>
bool Insert(T entity);
/// <summary>
/// 插入单个实体并返回ID
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
object InsertAndGetId(T entity);
/// <summary>
/// 批量插入数据集
/// </summary>
/// <param name="entities">数据集</param>
void Insert(IEnumerable<T> entities);
/// <summary>
/// 更新单个实体
/// </summary>
/// <param name="entity">实体</param>
/// <returns></returns>
bool Update(T entity);
/// <summary>
/// 批量更新数据集
/// </summary>
/// <param name="entities"></param>
void Update(IEnumerable<T> entities);
/// <summary>
/// 删除单个实体
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
bool Delete(T entity);
/// <summary>
/// 批量删除
/// </summary>
/// <param name="entities">删除的数据集</param>
void Delete(IEnumerable<T> entities);
/// <summary>
/// 通过ID删除实体
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
bool DeleteById(object id);
/// <summary>
/// 通过ID(逗号分隔ID)批量删除
/// </summary>
/// <param name="ids"></param>
/// <returns></returns>
bool DeleteByIds(object ids);
/// <summary>
/// 通过Id列表批量删除
/// </summary>
/// <param name="list"></param>
/// <returns></returns>
bool DeleteByIdList(List<object> list);
/// <summary>
/// 分页查询
/// </summary>
/// <param name="pageIndex">当前页</param>
/// <param name="pageSize">每页条数</param>
/// <param name="condition">lambda查询条件where</param>
/// <param name="orderName">排序字段 默认CreateTime</param>
/// <param name="sortOrder">排序方式 asc desc,默认CreateTime desc</param>
/// <returns></returns>
IPagedList<T> GetListForPaging(int pageIndex, int pageSize, Expression<Func<T, bool>> condition = null, string orderName = null, string sortOrder = null);
/// <summary>
/// Linq连表查询专用,获取单表所有数据请使用GetList
/// </summary>
IQueryable<T> Table { get; }
/// <summary>
/// 根据条件查找
/// </summary>
/// <param name="condition">lambda查询条件where</param>
/// <returns></returns>
T GetEntity(Expression<Func<T, bool>> condition);
/// <summary>
/// 分页查询(Linq分页方式)
/// </summary>
/// <param name="pageIndex">当前页</param>
/// <param name="pageSize">页码</param>
/// <param name="condition">lambda查询条件where</param>
/// <<param name="sort">排序key:排序字段,value:bool,true-desc,false-asc 默认:CreateTime desc</param>
/// <returns></returns>
IPagedList<T> GetListForPaging(int pageIndex, int pageSize, Expression<Func<T, bool>> condition = null, Dictionary<string, bool> sort = null);
/// <summary>
/// 执行原始SQL命令
/// </summary>
/// <param name="commandText">SQL命令</param>
/// <param name="parameters">参数</param>
/// <returns>影响的记录数</returns>
IEnumerable<TElement> SqlQuery<TElement>(string sql, params object[] parameters) where TElement : class, new();
/// <summary>
/// 执行SqlCommand
/// </summary>
/// <param name="sql">sql</param>
/// <param name="parameters">参数</param>
/// <returns></returns>
int ExecuteSqlCommand(string sql, params object[] parameters);
/// <summary>
/// 查询列表,默认返回整个表数据
/// </summary>
/// <param name="condition">lambda查询条件where</param>
/// <returns></returns>
List<T> GetList(Expression<Func<T, bool>> condition = null);
}
}

EFRepository:IEFRepository接口实现

 using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using Tools.Cache; namespace Data
{
public class EFRepository<T> : IRepository<T> where T : BaseEntity
{
private DbContext _context;
private DbSet<T> _entities;
private IStaticCacheManager _cacheManager;
public EFRepository(DbContext context, IStaticCacheManager cacheManager)
{
this._context = context;
_cacheManager = cacheManager;
} private DbSet<T> Entities
{
get
{
if (_entities == null)
{
_entities = this._context.Set<T>();
}
return _entities;
}
}
/// <summary>
/// Linq连表查询专用,获取单表所有数据请使用GetList
/// </summary>
public virtual IQueryable<T> Table
{
get {
return this.Entities;
}
}
/// <summary>
/// 通过ID获取单个实体
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public virtual T GetById(object id)
{
var cacheKey = typeof(T).Name+".GetById."+id;
return _cacheManager.Get(cacheKey, ()=>this.Entities.Find(id));
}
/// <summary>
/// 插入单个实体
/// </summary>
/// <param name="entity">实体</param>
/// <returns></returns>
public virtual bool Insert(T entity)
{
if (entity == null)
throw new ArgumentNullException(nameof(entity)); try
{
Entities.Add(entity);
_context.SaveChanges();
var cacheContain = typeof(T).Name;
_cacheManager.RemoveByContain(cacheContain);
}
catch (DbUpdateException exception)
{
//ensure that the detailed error text is saved in the Log
throw new Exception(GetFullErrorTextAndRollbackEntityChanges(exception), exception);
}
return true;
}
/// <summary>
/// 插入单个实体并返回ID
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public virtual object InsertAndGetId(T entity)
{
if (entity == null)
throw new ArgumentNullException(nameof(entity));
try
{
this.Entities.Add(entity);
this._context.SaveChanges();
var cacheContain = typeof(T).Name;
_cacheManager.RemoveByContain(cacheContain);
}
catch (DbUpdateException exception)
{
//ensure that the detailed error text is saved in the Log
throw new Exception(GetFullErrorTextAndRollbackEntityChanges(exception), exception);
}
return entity.Id;
}
/// <summary>
/// 批量插入数据集
/// </summary>
/// <param name="entities">数据集</param>
public virtual void Insert(IEnumerable<T> entities)
{
if (entities == null)
throw new ArgumentNullException(nameof(entities)); try
{
Entities.AddRange(entities);
_context.SaveChanges();
var cacheContain = typeof(T).Name;
_cacheManager.RemoveByContain(cacheContain);
}
catch (DbUpdateException exception)
{
//ensure that the detailed error text is saved in the Log
throw new Exception(GetFullErrorTextAndRollbackEntityChanges(exception), exception);
}
}
/// <summary>
/// 更新单个实体
/// </summary>
/// <param name="entity">实体</param>
/// <returns></returns>
public virtual bool Update(T entity)
{
if (entity == null)
throw new ArgumentNullException(nameof(entity));
try
{
this._context.Set<T>().Attach(entity);
Type _type = typeof(T);
PropertyInfo[] _properties = _type.GetProperties();
var entry = _context.Entry(entity);
foreach (PropertyInfo item in _properties)
{
if ("Id" == item.Name || "CreateTime" == item.Name || "CreatePerson" == item.Name)
{
continue;
} entry.Property(item.Name).IsModified = true;
}
this._context.SaveChanges();
var cacheContain = typeof(T).Name;
_cacheManager.RemoveByContain(cacheContain);
}
catch (DbUpdateException exception)
{
//ensure that the detailed error text is saved in the Log
throw new Exception(GetFullErrorTextAndRollbackEntityChanges(exception), exception);
}
return true;
}
/// <summary>
/// 批量更新数据集
/// </summary>
/// <param name="entities"></param>
public virtual void Update(IEnumerable<T> entities)
{
if (entities == null)
throw new ArgumentNullException(nameof(entities)); try
{
// Entities.UpdateRange(entities);
this._context.Set<T>().AttachRange(entities);
foreach (var entity in entities)
{
Type _type = typeof(T);
PropertyInfo[] _properties = _type.GetProperties();
var entry = _context.Entry(entity);
foreach (PropertyInfo item in _properties)
{
if ("Id" == item.Name || "CreateTime" == item.Name || "CreatePerson" == item.Name)
{
continue;
} entry.Property(item.Name).IsModified = true;
}
} _context.SaveChanges();
var cacheContain = typeof(T).Name;
_cacheManager.RemoveByContain(cacheContain);
}
catch (DbUpdateException exception)
{
//ensure that the detailed error text is saved in the Log
throw new Exception(GetFullErrorTextAndRollbackEntityChanges(exception), exception);
}
}
/// <summary>
/// 删除单个实体
/// </summary>
/// <param name="entity"></param>
/// <returns></returns>
public virtual bool Delete(T entity)
{
if (entity == null)
throw new ArgumentNullException(nameof(entity)); try
{
Entities.Remove(entity);
_context.SaveChanges();
var cacheContain = typeof(T).Name;
_cacheManager.RemoveByContain(cacheContain);
}
catch (DbUpdateException exception)
{
//ensure that the detailed error text is saved in the Log
throw new Exception(GetFullErrorTextAndRollbackEntityChanges(exception), exception);
}
return true;
}
/// <summary>
/// 批量删除
/// </summary>
/// <param name="entities">删除的数据集</param>
public virtual void Delete(IEnumerable<T> entities)
{
if (entities == null)
throw new ArgumentNullException(nameof(entities)); try
{
Entities.RemoveRange(entities);
_context.SaveChanges();
var cacheContain = typeof(T).Name;
_cacheManager.RemoveByContain(cacheContain);
}
catch (DbUpdateException exception)
{
//ensure that the detailed error text is saved in the Log
throw new Exception(GetFullErrorTextAndRollbackEntityChanges(exception), exception);
}
}
/// <summary>
/// 通过ID删除实体
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public virtual bool DeleteById(object id)
{
try
{
var item = this.Entities.Find(id);
if (item == null)
{
return false;
}
this.Entities.Remove(item);
this._context.SaveChanges();
var cacheContain = typeof(T).Name;
_cacheManager.RemoveByContain(cacheContain);
}
catch (DbUpdateException exception)
{
//ensure that the detailed error text is saved in the Log
throw new Exception(GetFullErrorTextAndRollbackEntityChanges(exception), exception);
}
return true;
}
/// <summary>
/// 通过ID(逗号分隔ID)批量删除
/// </summary>
/// <param name="ids"></param>
/// <returns></returns>
public virtual bool DeleteByIds(object ids)
{
try
{
var idArray = ids.ToString().Split(',');
for (int i = ; i < idArray.Length; i++)
{
var item = this.Entities.Find(idArray[i]);
if (item == null)
{
continue;
}
this.Entities.Remove(item);
}
this._context.SaveChanges();
var cacheContain = typeof(T).Name;
_cacheManager.RemoveByContain(cacheContain);
}
catch (DbUpdateException exception)
{
//ensure that the detailed error text is saved in the Log
throw new Exception(GetFullErrorTextAndRollbackEntityChanges(exception), exception);
}
return true;
}
/// <summary>
/// 通过Id列表批量删除
/// </summary>
/// <param name="list"></param>
/// <returns></returns>
public virtual bool DeleteByIdList(List<object> list)
{
try
{
for (int i = ; i < list.Count; i++)
{
var item = this.Entities.Find(list[i]);
if (item == null)
{
continue;
}
this.Entities.Remove(item);
}
this._context.SaveChanges();
var cacheContain = typeof(T).Name;
_cacheManager.RemoveByContain(cacheContain);
}
catch (DbUpdateException exception)
{
//ensure that the detailed error text is saved in the Log
throw new Exception(GetFullErrorTextAndRollbackEntityChanges(exception), exception);
}
return true;
} /// <summary>
/// 根据条件查找
/// </summary>
/// <param name="condition">lambda查询条件where</param>
/// <returns></returns>
public virtual T GetEntity(Expression<Func<T, bool>> condition)
{
var cacheKey = typeof(T) + "GetSingleOrDefault.Condition."+ condition.ToString();
return _cacheManager.Get(cacheKey,()=>this.Entities.Where(condition).SingleOrDefault());
}
/// <summary>
/// 分页查询(Linq分页方式)
/// </summary>
/// <param name="pageIndex">当前页</param>
/// <param name="pageSize">页码</param>
/// <param name="condition">lambda查询条件where</param>
/// <param name="sort">排序key:排序字段,value:bool,true-desc,false-asc,默认:CreateTime desc</param>
/// <returns></returns>
public virtual IPagedList<T> GetListForPaging(int pageIndex, int pageSize, Expression<Func<T, bool>> condition = null, Dictionary<string, bool> sort = null)
{
if (pageIndex < )
pageIndex = ;
var cacheKey = typeof(T).Name;
cacheKey = cacheKey + ".GetList";
List<T> data = null; if (condition != null)
{
cacheKey = cacheKey+ ".Condition." + condition.ToString();
} data = _cacheManager.Get<List<T>>(cacheKey); if(data != null)
{
if (sort != null)
{
foreach (var item in sort)
{
data = data.AsQueryable().OrderBy(item.Key, item.Value).ToList();
}
}
else
{
data = data.AsQueryable().OrderByDescending(x => x.CreateTime).ToList();
}
}
else
{
if(condition!=null)
{
data = this.Entities.Where(condition).ToList();
}
else
{
data = this.Entities.ToList();
}
_cacheManager.Set(cacheKey, data, ); data = data.AsQueryable().OrderByDescending(x => x.CreateTime).ToList();//无缓存默认返回排序后数据
} return new PagedList<T>(data, pageIndex, pageSize);
} /// <summary>
/// 执行原始SQL命令
/// </summary>
/// <param name="commandText">SQL命令</param>
/// <param name="parameters">参数</param>
/// <returns>影响的记录数</returns>
public virtual IEnumerable<TElement> SqlQuery<TElement>(string sql, params object[] parameters) where TElement : class, new()
{
DataTable dt = this._context.Database.SqlQuery(sql, parameters);
return dt.ToEnumerable<TElement>(); }
/// <summary>
/// 分页查询
/// </summary>
/// <param name="pageIndex">当前页</param>
/// <param name="pageSize">每页条数</param>
/// <param name="condition">lambda查询条件where</param>
/// <param name="orderName">排序字段 默认CreateTime</param>
/// <param name="sortOrder">排序方式 asc desc,默认CreateTime desc</param>
/// <returns></returns>
public virtual IPagedList<T> GetListForPaging(int pageIndex, int pageSize, Expression<Func<T, bool>> condition = null, string orderName = null, string sortOrder = null)
{
var cachekey = typeof(T).Name;
if (pageIndex < )
pageIndex = ;
if (orderName == null)
{
orderName = "CreateTime";
}
bool isDesc = true;
if(sortOrder!=null&&sortOrder.ToLower() == "asc")
{
isDesc = false;
} cachekey = cachekey + ".GetList"; if(condition!=null)
{
cachekey = cachekey + ".Condition." + condition.ToString();
} List<T> resultList = null; var cacheData = _cacheManager.Get<List<T>>(cachekey);
if (cacheData != null)
{
resultList = cacheData.AsQueryable().OrderBy(orderName, isDesc).ToList();
}
else
{
if (condition == null)
{
resultList = Entities.ToList();
}
else
{
resultList = Entities.Where(condition).ToList();
}
_cacheManager.Set(cachekey, resultList, );
} return new PagedList<T>(resultList, pageIndex, pageSize);
}
/// <summary>
/// 执行SqlCommand
/// </summary>
/// <param name="sql">sql</param>
/// <param name="parameters">参数</param>
/// <returns></returns>
public virtual int ExecuteSqlCommand(string sql, params object[] parameters)
{
var result = this._context.Database.ExecuteSqlCommand(sql, parameters);
return result;
}
/// <summary>
/// 查询列表,默认返回整个表数据
/// </summary>
/// <param name="condition">lambda查询条件where</param>
/// <returns></returns>
public virtual List<T> GetList(Expression<Func<T, bool>> condition = null)
{
var cacheKey = typeof(T).Name+ ".GetList";
List<T> entities = null;
if (condition != null)
{
cacheKey = cacheKey + ".Condition." + condition.ToString();
entities = _cacheManager.Get(cacheKey,()=>this.Entities.Where(condition).ToList());
}
else
{
entities = _cacheManager.Get(cacheKey,()=>this.Entities.ToList());
}
return entities;
}
#region Utilities /// <summary>
/// Rollback of entity changes and return full error message
/// </summary>
/// <param name="exception">Exception</param>
/// <returns>Error message</returns>
protected string GetFullErrorTextAndRollbackEntityChanges(DbUpdateException exception)
{
//rollback entity changes
if (_context is DbContext dbContext)
{
var entries = dbContext.ChangeTracker.Entries()
.Where(e => e.State == EntityState.Added || e.State == EntityState.Modified).ToList(); entries.ForEach(entry =>
{
try
{
entry.State = EntityState.Unchanged;
}
catch (InvalidOperationException)
{
// ignored
}
});
} try
{
_context.SaveChanges();
return exception.ToString();
}
catch (Exception ex)
{
//if after the rollback of changes the context is still not saving,
//return the full text of the exception that occurred when saving
return ex.ToString();
}
} #endregion }
}
public static class QueryableExtensions
{
public static IQueryable<T> OrderBy<T>(this IQueryable<T> queryable, string propertyName)
{
return QueryableHelper<T>.OrderBy(queryable, propertyName, false);
}
public static IQueryable<T> OrderBy<T>(this IQueryable<T> queryable, string propertyName, bool desc)
{
return QueryableHelper<T>.OrderBy(queryable, propertyName, desc);
}
static class QueryableHelper<T>
{
private static Dictionary<string, LambdaExpression> cache = new Dictionary<string, LambdaExpression>();
public static IQueryable<T> OrderBy(IQueryable<T> queryable, string propertyName, bool desc)
{
dynamic keySelector = GetLambdaExpression(propertyName);
return desc ? Queryable.OrderByDescending(queryable, keySelector) : Queryable.OrderBy(queryable, keySelector);
}
private static LambdaExpression GetLambdaExpression(string propertyName)
{
if (cache.ContainsKey(propertyName)) return cache[propertyName];
var param = Expression.Parameter(typeof(T));
var body = Expression.Property(param, propertyName);
var keySelector = Expression.Lambda(body, param);
cache[propertyName] = keySelector;
return keySelector;
}
}
}
   _cacheManager下篇我们讲到缓存管理的时候再来讲,包括依赖注入也放到下篇,今天就先到这里了!
05-11 22:52