前两篇简单谈了一些.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. mkdir,rmdir

    mkdir (选项)(参数)  创建文件夹-m:创建文件夹的同时,赋予其权限-p:若创建目录的上层不存在时,一并创建出来-v:显示创建的过程创建多个目录的时候,用空格隔开 rmdir (选项)(参数) ...

  2. linux无法安装应用

    需安装flex 和bison 一般需要更新软件源 root权限 下 apt-get update apt-get upgrade 如果出现以下问题,先查看网络是否畅通: ping 192.168.0. ...

  3. CentOS8 yum/dnf 配置国内源

    CentOS8 yum/dnf 配置国内源(临时) CentOS 8更改了软件包的安装程序,取消了 yum 的配置方法,改而使用了dnf 作为安装程序.虽然改变了软件包的安装方式,但是 dnf 还是能 ...

  4. ZGC深入学习

    ZGC简介 本次调研目标选取的是jdk11(long-term support)下首次亮相的zgc. zgc介绍简单翻译了zgc main page:ZGC简介 另外参考hotspot garbage ...

  5. MySQL索引的建立与实现

    一.索引介绍 1.MySQL中,所有的数据类型都可以被索引,索引包括普通索引,唯一性索引,全文索引,单列索引,多列索引和空间索引等. 2.额外的:我已知的自动创建索引的时机:创建主键,唯一,外键约束的 ...

  6. 快速入门Maven(一)

    一.Maven简介 1.什么是maven Apache组织中的一个颇为成功的开源项目,Maven主要服务于基于Java平台的项目构建.依赖管理和项目信息管理. 2.Maven的好处 构建是程序员每天要 ...

  7. Get https://172.18.255.243:6443/api/v1/namespaces/kube-system/configmaps/kubelet-config-1.12: dial tcp 172.18.255.243:6443: i/o timeout

    问题描述 使用外网加入集群的时候报如下错误: Get https://172.18.255.243:6443/api/v1/namespaces/kube-system/configmaps/kube ...

  8. SVN应用

    一:从服务器上down资料 1.在电脑上安装SVN客户端 2.在电脑本地创建个文件夹作为版本库 3.进入xfssvn文件夹右击鼠标选择SVN Checkout或SVN Update 4.输入服务器中配 ...

  9. 比较两个文件的异同Python3 标准库difflib 实现

    比较两个文件的异同Python3 标准库difflib 实现 对于要比较两个文件特别是配置文件的差异,这种需求很常见,如果用眼睛看,真是眼睛疼. 可以使用linux命令行工具diff a_file b ...

  10. PHP array_splice

    1.函数的作用:数组中元素的删除和替代 2.函数的参数: @params array  &$array @params int      $offset @params int      $l ...