回到目錄工作單元UoW我們幾乎在任務一個像樣的框架里都可以找到它的足跡,是的,對於大型系統來說,他是很重要的,保持數據一致性,維持事務狀態這都是它要為系統實現的功能,而在不同的框架里,實現UoW的機制也是不同的,在Lind.DDD中,採用了一種共同註冊,統一提交的方式來實現UoW!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,對於工作單元的探討今天就先說到這裡,以後肯定還是機會去研究的!