上一节我们讲到对EF(EntityFramework)的初步封装,任何事情都不可能一蹴而就,通过大量的实际项目的实战,也发现了其中的各种问题。在这一章中,我们对上一章的EF_Helper_DG进行优化,主要优化点如下:
1.由DB实体单例模式改为从缓存中获取;
2.加入服务器缓存,协助查询,提升查询性能;
3.优化CUD操作方法的执行方式;
下面直接展示新的EF_Helper_DG 代码:
using LinqKit; //AsExpandable() in linqkit.dll using System; using System.Linq; using System.Linq.Expressions; using System.Data.Entity; using System.Transactions; using QX_Frame.Helper_DG.Configs; namespace QX_Frame.Helper_DG { /* time: 2016-10-30 15:26:05 author: qixiao */ /// <summary> /// EntityFramework CodeFirst Helper /// </summary> /// <typeparam name="Db">DbContext</typeparam> public abstract class EF_Helper_DG<Db> where Db : DbContext { /*the singleton Db */ //private volatile static Db db = null; //volatile find Db in memory not in cache #region The Singleton to new DBEntity_DG //private static readonly object lockHelper = new object(); //static EF_Helper_DG() //{ // if (db == null) // { // lock (lockHelper) // { // if (db == null) // db = System.Activator.CreateInstance<Db>(); // } // } // //close the Validate of EF OnSaveEnabled // db.Configuration.ValidateOnSaveEnabled = false; //} #endregion #region get current dbContext public static DbContext GetCurrentDbContext() { //method 1 : CallContext 该方法有有时候第一次访问不到的bug //CallContext:是线程内部唯一的独用的数据槽(一块内存空间) //Db dbContext = CallContext.GetData("DbContext") as Db; //if (dbContext == null) //线程在内存中没有此上下文 //{ // //create a dbContext to memory if dbContext has not exist // dbContext = System.Activator.CreateInstance<Db>(); // CallContext.SetData("DbContext", dbContext); //} //method 2 : Db dbContext = Cache_Helper_DG.Cache_Get("dbContext") as Db; if (dbContext == null) { //create a dbContext to memory if dbContext has not exist dbContext = System.Activator.CreateInstance<Db>(); Cache_Helper_DG.Cache_Add("dbContext",dbContext); } return dbContext; } #endregion #region Cache Strategy /// <summary> /// edit data cache must update /// </summary> public static void CacheChanges<T>() { if (QX_Frame_Helper_DG_Config.Cache_IsCache) { Cache_Helper_DG.Cache_Delete(nameof(T)); } } /// <summary> /// query cache /// </summary> /// <typeparam name="T"></typeparam> /// <returns></returns> public static IQueryable<T> GetIQuerybleByCache<T>() where T : class { if (QX_Frame_Helper_DG_Config.Cache_IsCache) { IQueryable<T> iqueryable = Cache_Helper_DG.Cache_Get(nameof(T)) as IQueryable<T>; if (iqueryable == null) { DbContext db = GetCurrentDbContext(); iqueryable = db.Set<T>().AsExpandable(); Cache_Helper_DG.Cache_Add(nameof(T), iqueryable, null, DateTime.Now.AddMinutes(QX_Frame_Helper_DG_Config.Cache_CacheExpirationTime_Minutes), TimeSpan.Zero); } return iqueryable; } else { DbContext db = GetCurrentDbContext(); return db.Set<T>().AsExpandable(); } } #endregion #region Add public static Boolean Add<T>(T entity) where T : class { DbContext db = GetCurrentDbContext(); CacheChanges<T>(); db.Entry<T>(entity).State = EntityState.Added; ; } public static Boolean Add<T>(T entity, out T outEntity) where T : class { DbContext db = GetCurrentDbContext(); CacheChanges<T>(); db.Entry<T>(entity).State = EntityState.Added; outEntity = entity; ; } public static Boolean Add<T>(IQueryable<T> entities) where T : class { DbContext db = GetCurrentDbContext(); CacheChanges<T>(); db.Set<T>().AddRange(entities); ; } #endregion #region Update public static Boolean Update<T>(T entity) where T : class { DbContext db = GetCurrentDbContext(); CacheChanges<T>(); if (db.Entry<T>(entity).State == EntityState.Detached) { db.Set<T>().Attach(entity); db.Entry<T>(entity).State = EntityState.Modified; } else { db.SaveChanges(); return true; } ; } public static Boolean Update<T>(T entity, out T outEntity) where T : class { DbContext db = GetCurrentDbContext(); CacheChanges<T>(); outEntity = entity; if (db.Entry<T>(entity).State == EntityState.Detached) { db.Set<T>().Attach(entity); db.Entry<T>(entity).State = EntityState.Modified; } else { db.SaveChanges(); return true; } ; } #endregion #region Delete public static Boolean Delete<T>(T entity) where T : class { DbContext db = GetCurrentDbContext(); CacheChanges<T>(); db.Set<T>().Attach(entity); db.Entry<T>(entity).State = EntityState.Deleted; ; } public static Boolean Delete<T>(IQueryable<T> entities) where T : class { DbContext db = GetCurrentDbContext(); CacheChanges<T>(); db.Set<T>().RemoveRange(entities); ; } public static Boolean Delete<T>(Expression<Func<T, bool>> deleteWhere) where T : class { DbContext db = GetCurrentDbContext(); CacheChanges<T>(); IQueryable<T> entitys = GetIQuerybleByCache<T>().Where(deleteWhere); /** * change code 2017-5-6 11:11:19 qixiao * entitys.ForEach(m => db.Entry<T>(m).State = EntityState.Deleted); **/ entitys.ForEachAsync(m => db.Entry<T>(m).State = EntityState.Deleted); ; } #endregion #region Select public static Boolean Exist<T>(Expression<Func<T, Boolean>> selectWhere) where T : class { return GetIQuerybleByCache<T>().Where(selectWhere).FirstOrDefault<T>() == null ? false : true; } public static T selectSingle<T>(Expression<Func<T, Boolean>> selectWhere) where T : class { return GetIQuerybleByCache<T>().Where(selectWhere).FirstOrDefault<T>(); } public static IQueryable<T> selectAll<T>() where T : class { return GetIQuerybleByCache<T>(); } public static IQueryable<T> selectAll<T>(out int Count) where T : class { Count = GetIQuerybleByCache<T>().Count(); return GetIQuerybleByCache<T>(); } public static IQueryable<T> selectAll<T, TKey>(Expression<Func<T, TKey>> orderBy, Boolean isDESC = false) where T : class { if (isDESC) return GetIQuerybleByCache<T>().OrderByDescending(orderBy); else return GetIQuerybleByCache<T>().OrderBy(orderBy); } public static IQueryable<T> selectAll<T, TKey>(Expression<Func<T, TKey>> orderBy, out int Count, Boolean isDESC = false) where T : class { Count = GetIQuerybleByCache<T>().Count(); if (isDESC) return GetIQuerybleByCache<T>().OrderByDescending(orderBy); else return GetIQuerybleByCache<T>().OrderBy(orderBy); } public static IQueryable<T> selectAll<T>(Expression<Func<T, Boolean>> selectWhere) where T : class { return GetIQuerybleByCache<T>().Where(selectWhere); } public static IQueryable<T> selectAll<T>(Expression<Func<T, Boolean>> selectWhere, out int Count) where T : class { var IQueryable = GetIQuerybleByCache<T>().Where(selectWhere); Count = IQueryable.Count(); return IQueryable; } public static IQueryable<T> selectAll<T, TKey>(Expression<Func<T, TKey>> orderBy, Expression<Func<T, Boolean>> selectWhere, Boolean isDESC = false) where T : class { if (isDESC) return GetIQuerybleByCache<T>().Where(selectWhere).OrderByDescending(orderBy); else return GetIQuerybleByCache<T>().Where(selectWhere).OrderBy(orderBy); } public static IQueryable<T> selectAll<T, TKey>(Expression<Func<T, TKey>> orderBy, Expression<Func<T, Boolean>> selectWhere, out int Count, Boolean isDESC = false) where T : class { var IQueryable = GetIQuerybleByCache<T>().Where(selectWhere); Count = IQueryable.Count(); if (isDESC) return IQueryable.OrderByDescending(orderBy); else return IQueryable.OrderBy(orderBy); } public static IQueryable<T> selectAllPaging<T, TKey>(int pageIndex, int pageSize, Expression<Func<T, TKey>> orderBy, Boolean isDESC = false) where T : class { var IQueryable = GetIQuerybleByCache<T>(); if (isDESC) < ? : pageIndex - ) * (pageSize < ? : pageSize)).Take(pageSize < ? : pageSize); else < ? : pageIndex - ) * (pageSize < ? : pageSize)).Take(pageSize < ? : pageSize); } public static IQueryable<T> selectAllPaging<T, TKey>(int pageIndex, int pageSize, Expression<Func<T, TKey>> orderBy, out int Count, Boolean isDESC = false) where T : class { var IQueryable = GetIQuerybleByCache<T>(); Count = IQueryable.Count(); if (isDESC) < ? : pageIndex - ) * (pageSize < ? : pageSize)).Take(pageSize < ? : pageSize); else < ? : pageIndex - ) * (pageSize < ? : pageSize)).Take(pageSize < ? : pageSize); } public static IQueryable<T> selectAllPaging<T, TKey>(int pageIndex, int pageSize, Expression<Func<T, TKey>> orderBy, Expression<Func<T, Boolean>> selectWhere, Boolean isDESC = false) where T : class { var IQueryable = GetIQuerybleByCache<T>().Where(selectWhere); if (isDESC) < ? : pageIndex - ) * (pageSize < ? : pageSize)).Take(pageSize < ? : pageSize); else < ? : pageIndex - ) * (pageSize < ? : pageSize)).Take(pageSize < ? : pageSize); } public static IQueryable<T> selectAllPaging<T, TKey>(int pageIndex, int pageSize, Expression<Func<T, TKey>> orderBy, Expression<Func<T, Boolean>> selectWhere, out int Count, Boolean isDESC = false) where T : class { var IQueryable = GetIQuerybleByCache<T>().Where(selectWhere); Count = IQueryable.Count(); if (isDESC) < ? : pageIndex - ) * (pageSize < ? : pageSize)).Take(pageSize < ? : pageSize); else < ? : pageIndex - ) * (pageSize < ? : pageSize)).Take(pageSize < ? : pageSize); } #endregion #region Transaction public static void Transaction(Action action) { using (TransactionScope trans = new TransactionScope()) { action(); trans.Complete(); } } #endregion #region ExecuteSqlCommand public static void ExecuteSqlCommand(string sqlCommand) { DbContext db = GetCurrentDbContext(); db.Database.ExecuteSqlCommand(sqlCommand); } public static void ExecuteSqlCommand(string sqlCommand, params object[] parameters) { DbContext db = GetCurrentDbContext(); db.Database.ExecuteSqlCommand(sqlCommand, parameters); } #endregion } }
上述代码为当前版本的EF_Helper_DG代码,当然欢迎所有的同行们优化补充哦~