用工作单元(IUnitOfWork)带给我们的是什么?
用工作单元带给我们的是什么?... 1
1. 相关说明2. 优化查询3. 优化SubmitChanges4. 优化TransactionScope5. 核心代码
1. 相关说明
工作单元的接入,保证了数据上下文在一个操作单元中只有一个,它可以通过构造方法注入到其它类中,实现跨类进行方法的组合。
2. 优化查询
上面的问题产生的场合应该是:
你用了join语句,你的join语句与from语句所使用的数据上下文不是一个(DataContext)
解决方法:
将数据上下文变成一个就可以了,这就是之前我们一直用的线程单例模式出现的原因,而往往一个方法可能需要引用多个类中的方法,这时,线程单例将不能解决这个问题,这时,出现了IunitOfWork,工作单元的概念!
使用的场合:
BLL层引用多个BLL层的方法
BLL层引用多个DAL层的方法
可能出现的代码:
3. 优化SubmitChanges
将多个SubmitChanges语句合并成一个,然后提交意味着什么?它意味着你与数据库交互次数的降低,呵呵!
代码可能是这样:
4. 优化TransactionScope
对于不同数据上下文组合的事务来说,TransactionScope将会把它提升为分布式事务,这在MSDN上确实没有找到相关文档,只是实践证明出来的,呵呵,所以,对于使用TransactionScope的开发者来说,请同时使用IUnitOfWork模式吧,让不必出现的MSDTC不要随意出现!
5. 核心代码
BLL层基类:
/// <summary> /// 业务层抽象基类 /// </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文件中的XXB节点"); return System.Configuration.ConfigurationManager.ConnectionStrings["xxb"].ToString(); } } /// <summary> /// 通用消息 /// </summary> protected VMessage VMessage { get; set; } #endregion #region Methods /// <summary> /// 数据层统一操作对象实例 /// 避免派生类直接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,可以使用LoadRepository泛型方法直接操作实体对象,如果BLL层业务对象为业务复杂的,在将来可能需要互相引用对方的,这时,我们需要在BLL类中进行构造方法的重构,为IUnitOfWork实例的注入预留接口。
#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
有时,如果这个bll类需要使用BLLBase里的LoadRepository方法,需要为它的UnitOfWork属性赋值,为了保持代码的严禁性,我们只允许在基类构造方法中为它赋值,所以,一般bll子类的架构方法为:
public UserCenterManager() : base(new dbDataContext(XXBConn)) { _user_Info = new User_Info(UnitOfWork); _user_Profile = new User_Profile(UnitOfWork); _user_SchoolInfo = new User_SchoolInfo(UnitOfWork); }
上面的代码中,同时展示了BLL是如何去引用DAL对象的,User_Info同时接收一个IunitOfWork对象,而它的代码为:
public partial class User_Course : EEE114Base { public User_Course(IUnitOfWork iUnitOfWork) : base(iUnitOfWork) { }
事实上,它是将EEE114Base基类中传递了一个数据上下文,这些数据上下文都会继承IunitOfWork这个接口,并最终实现统一的提交动作,我们在开发中,建议为每个DAL类型都保留一个带有IunitOfWork参数的架构方法,这样才能保存我们的LINQ操作共处于一个数据上下文。