Lind.DDD.UoW工作单元的实现
工作单元UoW我们几乎在任务一个像样的框架里都可以找到它的足迹,是的,对于大型系统来说,他是很重要的,保持数据一致性,维持事务状态这都是它要为系统实现的功能,而在不同的框架里,实现UoW的机制也是不同的,在Lind.DDD中,采用了一种共同注册,统一提交的方式来实现UoW!
UoW结构图
我们来看一下大叔工作单元的代码实现,首先看一下IUnitOfWorkRepository,我们的仓储接口会实现它,以便之后我们的仓储对象可以添加到工作单元里
/// <summary> /// 工作单元中仓储接口CRUD操作 /// 需要使用工作单元的仓储,需要实现本接口(IRepository,IExtensionRepository) /// </summary> public interface IUnitOfWorkRepository { /// <summary> /// 添加实体 /// </summary> /// <param name="item"></param> void UoWInsert(IEntity item); /// <summary> /// 更新实体 /// </summary> /// <param name="item"></param> void UoWUpdate(IEntity item); /// <summary> /// 移除实体 /// </summary> /// <param name="item"></param> void UoWDelete(IEntity item); }
接下来,我们再来说一下IUnitOfWork接口,它是工作单元入口的接口,有添加到单元和提交单元两个方法,使用简单明了,内部有字典对象,用来存储要提交的操作,这也是工作单元的核心,IEntity是实体的标识接口,所有实体都要继承它,而IUnitOfWorkRepository是仓储的标识接口,所以仓储接口都要继承它。
/// <summary> /// 工作单元 /// 所有数据上下文对象都应该继承它,面向仓储的上下文应该与具体实现(存储介质,ORM)无关 /// </summary> public interface IUnitOfWork { /// <summary> /// 向工作单元中注册变更 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="entity"></param> /// <param name="type"></param> /// <param name="repository"></param> void RegisterChangeded(IEntity entity, SqlType type, IUnitOfWorkRepository repository); /// <summary> /// 向数据库提交变更 /// </summary> void Commit(); }
我们来看一下,大叔是如何实现IUnitOfWork接口的吧
/// <summary> /// 工作单元,主要用于管理事务性操作 /// Author:Lind.zhang /// </summary> public class UnitOfWork : IUnitOfWork { #region Fields /// <summary> /// 操作行为字典 /// </summary> private IDictionary<IEntity, IUnitOfWorkRepository> insertEntities; private IDictionary<IEntity, IUnitOfWorkRepository> updateEntities; private IDictionary<IEntity, IUnitOfWorkRepository> deleteEntities; #endregion #region Constructor public UnitOfWork() { insertEntities = new Dictionary<IEntity, IUnitOfWorkRepository>(); updateEntities = new Dictionary<IEntity, IUnitOfWorkRepository>(); deleteEntities = new Dictionary<IEntity, IUnitOfWorkRepository>(); } #endregion #region IUnitOfWork 成员 /// <summary> /// 事务提交 /// </summary> public void Commit() { try { using (TransactionScope transactionScope = new TransactionScope()) { foreach (var entity in insertEntities.Keys) { insertEntities[entity].UoWInsert(entity); } foreach (var entity in updateEntities.Keys) { updateEntities[entity].UoWUpdate(entity); } foreach (var entity in deleteEntities.Keys) { deleteEntities[entity].UoWDelete(entity); } transactionScope.Complete();//提交事务,程序中如果出错,这行无法执行,即事务不会被提交,这就类似于rollback机制 } } catch (Exception ex) { Logger.LoggerFactory.Instance.Logger_Error(ex); } } /// <summary> /// 注册数据变更 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="entity"></param> /// <param name="type"></param> public void RegisterChangeded(IEntity entity, SqlType type, IUnitOfWorkRepository repository) { switch (type) { case SqlType.Insert: insertEntities.Add(entity, repository); break; case SqlType.Update: updateEntities.Add(entity, repository); break; case SqlType.Delete: deleteEntities.Add(entity, repository); break; default: throw new ArgumentException("you enter reference is error."); } } #endregion }
工作单元在调用时也是非常方便的,两步完成,第一注意动作,第二提交事务,下面看一下DEMO的代码片断
unitOfWork.RegisterChangeded(entity, SqlType.Update, userRepository); var userExtension = userExtRepository.Find(entity.Id); userExtension.NickName = Request.Form["UserExtension.NickName"]; userExtension.School = Request.Form["UserExtension.School"]; unitOfWork.RegisterChangeded(userExtension, SqlType.Update, userExtRepository); unitOfWork.Commit();
OK,对于工作单元的探讨今天就先说到这里,以后肯定还是机会去研究的!