說說IUnitOfWork~我的IUnitOfWork+Repository架構
第一講 認識IUnitOfWork,為(wei)什么要出(chu)現IUnitOfWork接口第(di)二講(jiang) Linq to Sql與EntityFrameworks中的SubmtChanges()發生了什么事第三講 方法(fa)完整性與統一提交不沖突(tu)第四(si)講(jiang) DbContext對象(xiang)的創建應該向BLL層(ceng)公(gong)開第五(wu)講 我的IUnitOfWork+Repository架構
這個系統的文章在寫完這篇后將拉下眉目,一共5講的IUnitOfWork帶給我們的是性能,原子化操作,等多方法的改進,下面我把我的IUnitOfWork+Repository模式大體的說一下,并代上核心代碼:
底(di)層接口UnitOfWork.Data.Core
這是(shi)一個接口規范的(de)項(xiang)目(mu)層,它由CURD操(cao)作(zuo)規范和UnitOfWork規范組(zu)成
namespace UnitOfWork.Data.Core { /// <summary> /// 工作單元 /// 提供一個(ge)保存方法,它可以對(dui)調用層公(gong)開,為了減少連(lian)庫次數 /// </summary> public interface IUnitOfWork { /// <summary> /// 將操作(zuo)提交到數據庫(ku), /// </summary> void Save(); /// <summary> /// 是否不提交到(dao)數據庫(ku),這(zhe)只是在(zai)具體的(de)repository類中的(de)SaveChanges方法里用到(dao)的(de) /// 默認為false,即默認為提(ti)交(jiao)到(dao)數據庫(ku) /// </summary> /// <returns></returns> bool IsNotSubmit { get; set; } } /// <summary> /// 工作單元 /// 對泛型類型的支持 /// </summary> /// <typeparam name="T"></typeparam> public interface IUnitOfWork<T> : IUnitOfWork where T : class { } }
namespace UnitOfWork.Data.Core { public interface IRepository<TEntity> where TEntity : class { /// <summary> /// 添加實體并(bing)提交到數據(ju)服務器 /// </summary> /// <param name="item">Item to add to repository</param> void Insert(TEntity item); /// <summary> /// 移除實體并提交到(dao)數據服務器 /// 如果表(biao)存在約束(shu),需要先刪除子表(biao)信(xin)息(xi) /// </summary> /// <param name="item">Item to delete</param> void Delete(TEntity item); /// <summary> /// 修改實體并提交(jiao)到(dao)數(shu)據服務(wu)器 /// </summary> /// <param name="item"></param> void Update(TEntity item); /// <summary> /// Get all elements of type {T} in repository /// </summary> /// <returns>List of selected elements</returns> IQueryable<TEntity> GetModel(); /// <summary> /// 根據主鍵得到實體(ti) /// </summary> /// <param name="id"></param> /// <returns></returns> TEntity Find(params object[] id); } }
namespace UnitOfWork.Data.Core { /// <summary> /// 擴(kuo)展(zhan)的(de)Repository操作規范 /// </summary> public interface IExtensionRepository<TEntity> where TEntity : class { /// <summary> /// 添加(jia)集合 /// </summary> /// <param name="item"></param> void Insert(IEnumerable<TEntity> item); /// <summary> /// 修(xiu)改集合 /// </summary> /// <param name="item"></param> void Update(IEnumerable<TEntity> item); /// <summary> /// 刪除(chu)集合 /// </summary> /// <param name="item"></param> void Delete(IEnumerable<TEntity> item); /// <summary> /// 擴展更新方法,只對(dui)EF支(zhi)持 /// </summary> /// <param name="entity"></param> void Update(System.Linq.Expressions.Expression<Action<TEntity>> entity); } }
namespace UnitOfWork.Data.Core { /// <summary> /// 完整的數(shu)據(ju)操作(zuo)接口(kou) /// </summary> public interface ICompleteRepository<T> : IRepository<T>, IExtensionRepository<T> where T : class { } }
而在DATA層需要去(qu)實(shi)現(xian)這(zhe)些接口,我(wo)們(men)以EF為例,去(qu)實(shi)現(xian)這(zhe)樣接口:
namespace EntityFrameworks.Data.Core { using UnitOfWork.Data.Core; using System.Data.Entity.Infrastructure; public class DbContextRepository<TEntity> : ICompleteRepository<TEntity> where TEntity : class { protected DbContext _db { get; private set; } IUnitOfWork iUnitWork; public DbContextRepository(IUnitOfWork db) { iUnitWork = db; _db = (DbContext)db; } #region IRepository<T> 成員 public virtual void Insert(TEntity item) { _db.Entry<TEntity>(item); _db.Set<TEntity>().Add(item); this.SaveChanges(); } public virtual void Delete(TEntity item) { _db.Set<TEntity>().Attach(item); _db.Set<TEntity>().Remove(item); this.SaveChanges(); } public virtual void Update(TEntity item) { _db.Set<TEntity>().Attach(item); _db.Entry(item).State = EntityState.Modified; this.SaveChanges(); } public void Update(Expression<Action<TEntity>> entity) { TEntity newEntity = typeof(TEntity).GetConstructor(Type.EmptyTypes).Invoke(null) as TEntity;//建立(li)指定類型的實例 List<string> propertyNameList = new List<string>(); MemberInitExpression param = entity.Body as MemberInitExpression; foreach (var item in param.Bindings) { string propertyName = item.Member.Name; object propertyValue; var memberAssignment = item as MemberAssignment; if (memberAssignment.Expression.NodeType == ExpressionType.Constant) { propertyValue = (memberAssignment.Expression as ConstantExpression).Value; } else { propertyValue = Expression.Lambda(memberAssignment.Expression, null).Compile().DynamicInvoke(); } typeof(TEntity).GetProperty(propertyName).SetValue(newEntity, propertyValue, null); propertyNameList.Add(propertyName); } _db.Set<TEntity>().Attach(newEntity); _db.Configuration.ValidateOnSaveEnabled = false; var ObjectStateEntry = ((IObjectContextAdapter)_db).ObjectContext.ObjectStateManager.GetObjectStateEntry(newEntity); propertyNameList.ForEach(x => ObjectStateEntry.SetModifiedProperty(x.Trim())); this.SaveChanges(); // ((IObjectContextAdapter)_db).ObjectContext.Detach(newEntity); } public IQueryable<TEntity> GetModel() { // return _db.Set<TEntity>().AsNoTracking(); return _db.Set<TEntity>(); } #endregion #region IExtensionRepository<T> 成員 public virtual void Insert(IEnumerable<TEntity> item) { item.ToList().ForEach(i => { this.Insert(i);//不提交 }); } public virtual void Delete(IEnumerable<TEntity> item) { item.ToList().ForEach(i => { this.Delete(i); }); } public virtual void Update(IEnumerable<TEntity> item) { item.ToList().ForEach(i => { this.Update(i); }); } public TEntity Find(params object[] id) { return _db.Set<TEntity>().Find(id); } #endregion #region Protected Methods /// <summary> /// 根(gen)據工作單元的IsNotSubmit的屬(shu)性,去判斷是否提交到數據庫 /// 一般地(di),在多個repository類型進行(xing)組合(he)時(shi),這(zhe)個IsNotSubmit都會設為(wei)true,即不馬上提交, /// 而(er)對于單個repository操(cao)作來說,它的(de)(de)(de)值(zhi)不需要設置,使用默認的(de)(de)(de)false,將直接(jie)提交到數據庫,這(zhe)也(ye)保(bao)證了操(cao)作的(de)(de)(de)原子(zi)性。 /// </summary> protected void SaveChanges() { if (!iUnitWork.IsNotSubmit) iUnitWork.Save(); } /// <summary> /// 計數更新,與SaveChange()是兩個SQL鏈接,走分布式(shi)事務 /// 子類(lei)可以根據自己(ji)的邏輯(ji),去復寫 /// tableName:表(biao)名(ming) /// param:索引0為(wei)主鍵名,1表主鍵值(zhi),2為(wei)要計數的字段,3為(wei)增量 /// </summary> /// <param name="tableName">表名</param> /// <param name="param">參數列表(biao),索(suo)引(yin)0為主鍵名,1表(biao)主鍵值(zhi),2為要計數的字段(duan),3為增量</param> protected virtual void UpdateForCount(string tableName, params object[] param) { string sql = "update [" + tableName + "] set [{2}]=ISNULL([{2}],0)+{3} where [{0}]={1}"; List<object> listParasm = new List<object> { param[0], param[1], param[2], param[3], }; _db.Database.ExecuteSqlCommand(string.Format(sql, listParasm.ToArray())); } #endregion } }
在Entity實(shi)體模(mo)型層,需要(yao)去繼承IUnitOfWork這個接口,并去實(shi)現(xian)它:
public partial class backgroundEntities : IUnitOfWork { #region IUnitOfWork 成員 public void Save() { this.SaveChanges(); } public bool IsNotSubmit { get; set; } #endregion }
最后在BLL層來完成(cheng)業務(wu)的組成(cheng)及基(ji)礎操作的實現
namespace BLL { public abstract class BLLBase { protected IUnitOfWork IUnitOfWork { get; private set; } public BLLBase() : this(null) { } public BLLBase(IUnitOfWork iUnitOfWork) { IUnitOfWork = iUnitOfWork; } protected ICompleteRepository<T> LoadRepository<T>() where T : class { return IUnitOfWork == null ? new TestBase<T>() : new TestBase<T>(IUnitOfWork); } } }
在BLL層(ceng)具體(ti)業務實現(xian)中,去繼承BLLBase,并將數據(ju)上下(xia)文以參數的形(xing)式傳(chuan)遞(di)過去:
public class OrderManager : BLLBase { public OrderManager() : base(new TestDataContext()) { } public void GeneratorOrder(Order_Info order) { GeneratorOrder(order, null); } public void GeneratorOrder(Order_Info order, Product product) { #region BLLBase中直接調用公用方法 IUnitOfWork.IsNotSubmit = true; new OrderRepository(IUnitOfWork).Insert(order);//DAL層具體的Repository實現類 if (product != null) LoadRepository<Product>().Insert(product);//BLLBase提供的單純(chun)CURD操作(zuo) IUnitOfWork.SaveChanges(); #endregion } }
在WEB層直接調用(yong)BLL的具體業務即可!
到此,我們的UnitOfWork系列就講完了,各位,晚安了!