用工(gong)作單(dan)元(yuan)(IUnitOfWork)帶(dai)給我們的是什么?
用工作單元帶給我(wo)們的是什么?... 1
1. 相(xiang)關說明2. 優化(hua)查詢3. 優化(hua)SubmitChanges4. 優(you)化TransactionScope5. 核心代(dai)碼
1. 相關說明
工作單(dan)元的(de)(de)接入(ru),保證了數據上下文在一(yi)個操作單(dan)元中只(zhi)有一(yi)個,它可以通過構造方法注(zhu)入(ru)到其它類中,實(shi)現跨類進行方法的(de)(de)組合(he)。
2. 優化查詢
上(shang)面的(de)問題產生的(de)場(chang)合應(ying)該(gai)是:
你(ni)用了join語句(ju),你(ni)的join語句(ju)與from語句(ju)所使(shi)用的數據上下文不是一個(DataContext)
解決方法:
將(jiang)數據上下文變成一(yi)個(ge)就(jiu)可以了(le),這(zhe)就(jiu)是之前我們一(yi)直用(yong)的(de)(de)線程(cheng)單(dan)例模式出現(xian)(xian)的(de)(de)原因(yin),而往(wang)往(wang)一(yi)個(ge)方法可能(neng)需要引用(yong)多個(ge)類中(zhong)的(de)(de)方法,這(zhe)時,線程(cheng)單(dan)例將(jiang)不能(neng)解(jie)決這(zhe)個(ge)問題,這(zhe)時,出現(xian)(xian)了(le)IunitOfWork,工作單(dan)元(yuan)的(de)(de)概念(nian)!
使用的場合:
BLL層(ceng)引用(yong)多個BLL層(ceng)的方法
BLL層引用多(duo)個DAL層的方(fang)法
可能出現的代碼:
3. 優化SubmitChanges
將(jiang)多個SubmitChanges語句合并成(cheng)一個,然后提(ti)交意(yi)味(wei)著(zhu)什(shen)么?它意(yi)味(wei)著(zhu)你與數據庫交互次數的降低(di),呵呵!
代碼可能是這樣:
4. 優化TransactionScope
對于不(bu)(bu)同數據上下文組合的事務來(lai)說,TransactionScope將會把它提升為分布式事務,這在MSDN上確(que)實沒有(you)找到相關文檔,只是(shi)實踐證明出來(lai)的,呵(he)呵(he),所以(yi),對于使用TransactionScope的開(kai)發(fa)者來(lai)說,請同時使用IUnitOfWork模式吧,讓不(bu)(bu)必出現的MSDTC不(bu)(bu)要隨意出現!
5. 核心代碼
BLL層基類:
/// <summary> /// 業務(wu)層抽象基類(lei) /// </summary> public abstract class BLLBase { #region Constructors public BLLBase() : this(null) { } public BLLBase(IUnitOfWork iUnitOfWork) { this.UnitOfWork = iUnitOfWork; this.VMessage = new VMessage(); } #endregion #region Fields & Properties /// <summary> /// 工作單元對象,由子類初始化 /// </summary> protected IUnitOfWork UnitOfWork { get; private set; } /// <summary> /// XXB連接串 /// </summary> protected static string XXBConn { get { if (System.Configuration.ConfigurationManager.ConnectionStrings["xxb"] == null) throw new ArgumentException("請配置在config文(wen)件(jian)中的XXB節點"); return System.Configuration.ConfigurationManager.ConnectionStrings["xxb"].ToString(); } } /// <summary> /// 通用消息 /// </summary> protected VMessage VMessage { get; set; } #endregion #region Methods /// <summary> /// 數據(ju)層統一(yi)操(cao)作對(dui)象實(shi)例 /// 避(bi)免派生類直接new對象 /// </summary> /// <typeparam name="TEntity"></typeparam> /// <param name="iUnitOfWork"></param> /// <returns></returns> protected ICompleteRepository<TEntity> LoadRepository<TEntity>() where TEntity : class,Entity.IDataEntity { return UnitOfWork == null ? new EEE114Repository<TEntity>() : new EEE114Repository<TEntity>(UnitOfWork); } #endregion }
BLL層業務類繼承BLLBase,可以(yi)使(shi)用LoadRepository泛型方法直(zhi)接(jie)操(cao)作實體(ti)對(dui)象,如(ru)果BLL層業務對(dui)象為(wei)業務復雜的(de),在(zai)將來可能需要互相引(yin)用對(dui)方的(de),這時,我們需要在(zai)BLL類中進行構(gou)(gou)造方法的(de)重構(gou)(gou),為(wei)IUnitOfWork實例的(de)注入預留接(jie)口。
#region Constructors public User_CourseManager() : this(null) { } public User_CourseManager(IUnitOfWork iUnitOfWork) : base(iUnitOfWork) { res_ItemCategory = new DAL.Res_ItemCategory(UnitOfWork); iResourceService = new Res_ItemService(); user_CourseRepository = new DAL.User_Course(UnitOfWork); iCommon_CategoryServices = new BLL.Common_CategoryServices(UnitOfWork); } #endregion
有時,如果這(zhe)個bll類需(xu)要使用BLLBase里的(de)(de)LoadRepository方法,需(xu)要為它的(de)(de)UnitOfWork屬性賦(fu)值,為了保持代碼的(de)(de)嚴禁性,我們只允許在基類構造方法中為它賦(fu)值,所以,一般bll子類的(de)(de)架構方法為:
public UserCenterManager() : base(new dbDataContext(XXBConn)) { _user_Info = new User_Info(UnitOfWork); _user_Profile = new User_Profile(UnitOfWork); _user_SchoolInfo = new User_SchoolInfo(UnitOfWork); }
上面的代碼中,同時展(zhan)示了BLL是如何去引用DAL對象的,User_Info同時接收(shou)一個IunitOfWork對象,而它的代碼為:
public partial class User_Course : EEE114Base { public User_Course(IUnitOfWork iUnitOfWork) : base(iUnitOfWork) { }
事實上(shang),它是(shi)將EEE114Base基類中(zhong)傳遞了一個數據上(shang)下文,這(zhe)些(xie)數據上(shang)下文都會繼承IunitOfWork這(zhe)個接口,并最終(zhong)實現統一的提交動(dong)作(zuo),我(wo)們在開發中(zhong),建議為每個DAL類型都保留一個帶有IunitOfWork參數的架構方(fang)法,這(zhe)樣才能保存我(wo)們的LINQ操作(zuo)共處于一個數據上(shang)下文。