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

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

Business:业务实现层

Domains:实体(Model)

Service:接口

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

EasyCacheing:开源缓存管理

Tools:工具类库

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

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

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下篇我们讲到缓存管理的时候再来讲,包括依赖注入也放到下篇,今天就先到这里了!

框架搭建与EF常用基类实现的更多相关文章

  1. Entity Framework 实体框架的形成之旅--基类接口的统一和异步操作的实现(3)

    在本系列的第一篇随笔<Entity Framework 实体框架的形成之旅--基于泛型的仓储模式的实体框架(1)>中介绍了Entity Framework 实体框架的一些基础知识,以及构建 ...

  2. Python接口测试实战4(下) - 框架完善:用例基类,用例标签,重新运行上次失败用例

    如有任何学习问题,可以添加作者微信:lockingfree 课程目录 Python接口测试实战1(上)- 接口测试理论 Python接口测试实战1(下)- 接口测试工具的使用 Python接口测试实战 ...

  3. 第六节:框架搭建之EF的Fluent Api模式的使用流程

    一. 前言 沉寂了约一个月的时间,今天用一篇简单的文章重新回归博客,主要来探讨一下Fluent Api模式在实际项目中的使用流程. 1. Fluent API属于EF CodeFirst模式的一种,E ...

  4. python3+selenium框架设计04-封装测试基类

    在完成了日志类封装之后,那我们就要对测试基类进行实现,在其中对一些请求再次封装,在项目下新建一个framework文件夹,在文件夹下新建Base_Page.py文件,这是用来写测试基类的文件.在项目下 ...

  5. Unity 游戏框架搭建 2019 (二十五) 类的第一个作用 与 Obselete 属性

    在上一篇我们整理到了第七个示例,我们今天再接着往下整理.我们来看第八个示例: #if UNITY_EDITOR using UnityEditor; #endif using UnityEngine; ...

  6. EF6增改删等常用基类

    using System; using System.Linq; using System.Threading.Tasks; using System.Linq.Expressions; using ...

  7. Entity Framework 实体框架的形成之旅--为基础类库接口增加单元测试,对基类接口进行正确性校验(10)

    本篇介绍Entity Framework 实体框架的文章已经到了第十篇了,对实体框架的各个分层以及基类的封装管理,已经臻于完善,为了方便对基类接口的正确性校验,以及方便对以后完善或扩展接口进行回归测试 ...

  8. EntityFramework 基类重写

    /* * ------------------------------------------------------------------------------ * * 创 建 者:F_Gang ...

  9. BIM工程信息管理系统-EF实体框架数据操作基类

    EF实体框架数据操作基类主要是规范增.改.查.分页.Lambda表达式条件处理,以及异步操作等特性,这样能够尽可能的符合基类这个特殊类的定义,实现功能接口的最大化重用和统一. 1.程序代码 /// & ...

随机推荐

  1. 【SQL server基础】object_id()函数

    在SQLServer数据库中,如果查询数据库中是否存在指定名称的索引或者外键约束等,经常会用到object_id('name','type')方法,做笔记如下: ? 语法:object_id('obj ...

  2. 如何评价一个VR体验设计?

    如何评价一个VR系统的体验是好是坏?或者说,哪些因素会破坏一个VR的体验? Kruij和Riecke教授在IEEE VR会议上提到了四个角度:Congnition,Game User Experien ...

  3. InnoDB引擎的启动过程

    一 前言 一直对InnoDB引擎的启动过程不太了解,查资料整理了下InnoDB引擎启动的过程和关闭过程,后续会整理些有关redo   undo 的知识点. 二 思维导图 三 参考文章 MySQL运维内 ...

  4. Flume 学习笔记之 Flume NG高可用集群搭建

    Flume NG高可用集群搭建: 架构总图: 架构分配: 角色 Host 端口 agent1 hadoop3 52020 collector1 hadoop1 52020 collector2 had ...

  5. MongoDB 走马观花(全面解读篇)

    目录 一.简介 二.基本模型 BSON 数据类型 分布式ID 三.操作语法 四.索引 索引特性 索引分类 索引评估.调优 五.集群 分片机制 副本集 六.事务与一致性 一致性 小结 一.简介 Mong ...

  6. 11g bug event 'cursor: mutex S'-引发的CPU冲高问题

    问题背景:客户反应数据库服务器CPU占用过高 1> 确认问题根源登录客户DB服务器: top 查看当前负载 (几乎100%)top - 10:47:55 up 29 days, 21:51, 3 ...

  7. 为什么那么多自学JAVA的后来都放弃了?总结起来就这些原因

    目前信息化产业发展势头很好,互联网就成为了很多普通人想要涉及的行业,因为相比于传统行业,互联网行业涨薪幅度大,机会也多,所以就会大批的人想要转行来学习Java开发. 目前来讲市场上需要的Java人员非 ...

  8. springboot redis-cache 自动刷新缓存

    这篇文章是对上一篇 spring-data-redis-cache 的使用 的一个补充,上文说到 spring-data-redis-cache 虽然比较强悍,但还是有些不足的,它是一个通用的解决方案 ...

  9. C语言--最大公约数

    //辗转相除法 int main() { int a,b; int t; scanf("%d %d", &a,&b); ) { t = a%b; a = b; b ...

  10. 了解一下Spring中用了哪些设计模式?这样回答面试官才稳

    一:简单工厂模式 又叫做静态工厂方法(StaticFactory Method)模式,但不属于23种GOF设计模式之一. 简单工厂模式的实质是由一个工厂类根据传入的参数,动态决定应该创建哪一个产品类. ...