文章出處

回到目錄

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

回到目錄


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()