1. 程式人生 > >Lind.DDD.UoW工作單元的實現

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,對於工作單元的探討今天就先說到這裡,以後肯定還是機會去研究的!

回到目錄