zoukankan      html  css  js  c++  java
  • UnitOfWork机制的实现和注意事项

    UnitOfWork机制

    /*一点牢骚:
     * UnitOfWork机制的蛋疼之处:
     *    UnitOfWork机制,决定了插入新的实体前,要预先设置数据库中的主键Id,尽管数据库自己生产主键。
     * 但是,如果自己能生成主键还要数据库自动生成主键干什么,即使自己生成主键不能保证主键的唯一性,
     * 除非主键是GUID。
     *   
     *               if (!addedEntities.ContainsKey(entity))
                    {
                        addedEntities.Add(entity, unitofWorkRepository);
                    };
     * 判断实体的唯一性标准是调用实体的GetHashCode();
     *      public override int GetHashCode()
            {
                return this.Id.GetHashCode();
            }
     *而 this.Id是实体在数据库的主键(一般用数据库自动生成),但我插入前怎么能由我生成能。
     *如果人工生成不能保证主键的唯一性,就不能添加到所以addedEntities中,也就不能保存到数据库。
     *折中的解决方案是每添加一个新的实体,就Commit一次(马上提交到数据库,并清空addedEntities)。
     * 
     */

    ---------------------------------------------------------冷静分割线---------------------------------------------------

    仓储实现UintOfWork机制

    1.目标:

      实现仓储实现UintOfWork机制(UintOfWork机制的目的是实现实体的持久化操作的原子性,保证数据的一致性)

    2.具体的实现思路:

         图解:

         

         伪代码:

    (1)仓储类Repository的定义

     Repository类
    {
          虚拟增(实体entity)
    
         {
               UintOfWork对象.增登记(实体entity,this)
    
        };
    
          虚拟删(实体entity)
    
         {
               UintOfWork对象.删登记(实体entity,this)
    
        };
    
          虚拟改Add(实体entity)
    
         {
               UintOfWork对象. 改登记(实体entity,this)
    
        };
        
    
          真的增到数据库(实体entity)
    
         {
               AddTo数据库(实体entity)
        };
    
          真的删到数据库(实体entity)
    
         {
               RemovFrom数据库(实体entity)
        };
    
          真的改保存到数据库(实体entity)
    
         {
               UpdateTo数据库(实体entity)
        };
    }

    (2)UnitOfWork类的定义:

    UnitOfWork
    {
    
           被增实体的字典 = new ();
           被删实体的字典 = new ();
           被改实体的字典 = new();
    
          增登记(实体entity,Repository)
         {
    if(如果被增实体的字典包不含实体entity) 被增实体的字典.Add(实体entity,Repository); } 删登记(实体entity,Repository) {
           
    if (如果被删实体的字典不包含实体enity) 被删实体的字典.Add(实体entity,Repository); } 改登记(实体entity,Repository) {

    if(如果被改实体的字典不包含实体entity) 被改实体的字典.Add(实体entity,Repository); } 统一提交到数据库Commit() {
    for(int i = 0 ; i < 被增实体的字典.lengh; ++i ) { 实体entity tmpEntity = 被增实体的字典[i].Key; Repository repository = 被增实体的字典[i].Value; repository.真的增保存到数据库(tmpEntity); } for(int i = 0 ; i < 被删实体的字典.lengh; ++i ) { 实体entity tmpEntity = 被删实体的字典[i].Key; Repository repository = 被删实体的字典[i].Value; repository.真的删保存到数据库(tmpEntity); } for(int i = 0 ; i < 被改实体的字典.lengh; ++i ) { 实体entity tmpEntity = 被改实体的字典[i].Key; Repository repository = 被改实体的字典[i].Value; repository.真的改保存到数据库(tmpEntity); } } }

    3.光说不练,代码实现:

    IUnitOfWorkRepository.cs

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Linq;
     4 using System.Text;
     5 using NCS.Infrastructure.Domain;
     6 
     7 namespace NCS.Infrastructure.UnitOfWork
     8 {
     9     /// <summary>
    10     /// Repository实现了UnitOfWork机制的Repository
    11     /// </summary>
    12     public interface IUnitOfWorkRepository
    13     {
    14         /// <summary>
    15         /// 实体的持久化操作(包括三个操作:增Add、删remove、改save,注意不包括查询)前,
    16         /// 先用UnitOfWork进行登记,
    17         /// 以便日后由UnitOfWork统一(原子性)通过Commit操作,提交修改到数据库(持久化操作)
    18         /// </summary>
    19         IUnitOfWork UnitOfWork { get; set; }
    20 
    21         /**
    22          * Persist持久化系列函数
    23          */
    24         void PersistCreationOf(IAggregateRoot entity);
    25         void PersistUpdateOf(IAggregateRoot entity);
    26         void PersistDeletionOf(IAggregateRoot entity);
    27     }
    28 }

    IUnitOfWork.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using NCS.Infrastructure.Domain;
    
    namespace NCS.Infrastructure.UnitOfWork
    {
        /// <summary>
        /// UnitOfWork模式:
        /// 1.跟踪领域实体聚合的变化
        /// 2.原子操作中完成实体聚合的持久化
        /// 3.具体实现:
        /// 实体的进行持久化操作(包括三个操作:增Add、删remove、改save,注意不包括查询)前,
        /// 先用UnitOfWork进行登记,
        /// 以便日后由UnitOfWork统一(原子性)通过Commit操作,提交修改到数据库(持久化操作)
        /// </summary>
        /// </summary>
        public interface IUnitOfWork
        {
            /// <summary>
            /// 注册登记被添加的实体
            /// </summary>
            /// <param name="entity">目标实体</param>
            /// <param name="unitofWorkRepository">实体所在的仓储</param>
            void RegisterNew(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository);
            /// <summary>
            /// 注册登记被删除的实体
            /// </summary>
            /// <param name="entity">目标实体</param>
            /// <param name="unitofWorkRepository">实体所在的仓储</param>
            void RegisterRemoved(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository);
            /// <summary>
            /// 注册登记被修改的实体
            /// </summary>
            /// <param name="entity">目标实体</param>
            /// <param name="unitofWorkRepository">实体所在的仓储</param>
            void RegisterAmended(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository);
    
            void Commit();
        }
    }

    AdoUnitOfWork.cs

      1 /*一点牢骚:
      2  * UnitOfWork机制的蛋疼之处:
      3  *    UnitOfWork机制,决定了插入新的实体前,要预先设置数据库中的主键Id,尽管数据库自己生产主键。
      4  * 但是,如果自己能生成主键还要数据库自动生成主键干什么,即使自己生成主键不能保证主键的唯一性,
      5  * 除非主键是GUID。
      6  *    
      7  *               if (!addedEntities.ContainsKey(entity))
      8                 {
      9                     addedEntities.Add(entity, unitofWorkRepository);
     10                 }; 
     11  * 判断实体的唯一性标准是调用实体的GetHashCode();
     12  *      public override int GetHashCode()
     13         {
     14             return this.Id.GetHashCode();
     15         }
     16  *而 this.Id是实体在数据库的主键(一般用数据库自动生成),但我插入前怎么能由我生成呢!!!
     17  *因为:
     18  *1.不知主键的数据库类型;
     19  *2.即使知道主键的数据库类型,也不能因为硬编码造成的依赖,耦合。
     20  *3.人工生成不能保证主键的唯一性,
     21  *综上,所以就不能添加到addedEntities中,也就不能保存到数据库。
     22  *折中的解决方案是每添加一个新的实体,就Commit一次(马上提交到数据库,并清空addedEntities)。
     23  *  
     24  */
     25 
     26 using System;
     27 using System.Collections.Generic;
     28 using System.Linq;
     29 using System.Text;
     30 using NCS.Infrastructure.Domain;
     31 using NCS.Infrastructure.UnitOfWork;
     32 using System.Transactions;
     33 
     34 namespace NCS.Repository.ADO
     35 {
     36     public class AdoUnitOfWork : IUnitOfWork
     37     {
     38         private Dictionary<IAggregateRoot, IUnitOfWorkRepository> addedEntities;
     39         private Dictionary<IAggregateRoot, IUnitOfWorkRepository> changedEntities;
     40         private Dictionary<IAggregateRoot, IUnitOfWorkRepository> deletedEntities;
     41 
     42         public AdoUnitOfWork()
     43         {
     44             addedEntities = new Dictionary<IAggregateRoot, IUnitOfWorkRepository>();
     45             changedEntities = new Dictionary<IAggregateRoot, IUnitOfWorkRepository>();
     46             deletedEntities = new Dictionary<IAggregateRoot, IUnitOfWorkRepository>();
     47         }
     48 
     49         #region IUnitOfWork member
     50 
     51         #region 注册登记实体
     52         public void RegisterNew(IAggregateRoot entity,
     53                                 IUnitOfWorkRepository unitofWorkRepository)
     54         {
     55             if (!addedEntities.ContainsKey(entity))
     56             {
     57                 addedEntities.Add(entity, unitofWorkRepository);
     58             }; 
     59         }
     60 
     61         public void RegisterRemoved(IAggregateRoot entity,
     62                                     IUnitOfWorkRepository unitofWorkRepository)
     63         {
     64             if (!deletedEntities.ContainsKey(entity))
     65             {
     66                 deletedEntities.Add(entity, unitofWorkRepository);
     67             }
     68         }
     69 
     70         public void RegisterAmended(IAggregateRoot entity,
     71                             IUnitOfWorkRepository unitofWorkRepository)
     72         {
     73             if (!changedEntities.ContainsKey(entity))
     74             {
     75                 changedEntities.Add(entity, unitofWorkRepository);
     76             }
     77         }
     78 
     79         #endregion
     80         public void Commit()
     81         {
     82             using (TransactionScope scope = new TransactionScope())
     83             {
     84                 foreach (IAggregateRoot entity in this.addedEntities.Keys)
     85                 {
     86                     this.addedEntities[entity].PersistCreationOf(entity);
     87                 }
     88 
     89                 foreach (IAggregateRoot entity in this.changedEntities.Keys)
     90                 {
     91                     this.changedEntities[entity].PersistUpdateOf(entity);
     92                 }
     93 
     94                 foreach (IAggregateRoot entity in this.deletedEntities.Keys)
     95                 {
     96                     this.deletedEntities[entity].PersistDeletionOf(entity);
     97                 }
     98 
     99                 scope.Complete();
    100 
    101                 this.addedEntities.Clear();
    102                 this.changedEntities.Clear();
    103                 this.deletedEntities.Clear();
    104             }
    105         }
    106 
    107         #endregion
    108 
    109     }
    110 }

    Repository.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using NCS.Infrastructure.Domain;
    using NCS.Infrastructure.Querying;
    using NCS.Infrastructure.UnitOfWork;
    using NCS.Repository.ADO.DataSession;
    
    namespace NCS.Repository.ADO.Repositories
    {
        public abstract class Repository<T, TEntityKey> : IUnitOfWorkRepository
            where T : IAggregateRoot
        {
            private IUnitOfWork unitOfWork;
    
            private IDataSession<T, TEntityKey> dataSession;
    
            public Repository(IUnitOfWork unitOfWork)
            {
                this.UnitOfWork = unitOfWork;
                DataSession = DataSessionFactory.GetDataSession<T, TEntityKey>();
            }
    
            public IUnitOfWork UnitOfWork
            {
                get { return unitOfWork; }
                set { unitOfWork = value; }
            }
    
            public IDataSession<T, TEntityKey> DataSession
            {
                get { return dataSession; }
                set { dataSession = value; }
            }
    
            #region 持久化
    
            public void Add(T entity)
            {
                UnitOfWork.RegisterNew(entity, this);
            }
    
            public void Remove(T entity)
            {
                UnitOfWork.RegisterNew(entity, this);
            }
    
            public void Remove(Query query)
            {
                //TODO:好像Remove(Query query)并不能保证事务操作,因为没添加到UnitOfWork里面
                //先提交事务
                unitOfWork.Commit();
    
                DataSession = DataSessionFactory.GetDataSession<T, TEntityKey>();
                DataSession.Remove(query);
    
            }
    
            public void Save(T entity)
            {
                UnitOfWork.RegisterRemoved(entity, this);
            }
    
            #endregion
    
            #region 查询部分
    
            public T FindBy(TEntityKey id)
            {
                return this.DataSession.FindBy(id);
            }
    
            public IEnumerable<T> FindAll()
            {
                return this.DataSession.FindAll();
            }
    
            public IEnumerable<T> FindAll(int index, int count)
            {
                return this.DataSession.FindAll().Skip(index).Take(count);
            }
    
            public IEnumerable<T> FindBy(Query query)
            {
                return this.DataSession.FindBy(query);
            }
    
            public IEnumerable<T> FindBy(Query query, int index, int count)
            {
                return this.DataSession.FindBy(query, index, count);
            }
    
            #endregion
    
            #region IUnitOfWorkRepository members
    
            public virtual void PersistCreationOf(IAggregateRoot entity)
            {
                this.DataSession.Add((T)entity);
            }
    
            public virtual void PersistUpdateOf(IAggregateRoot entity)
            {
                this.DataSession.Save((T)entity);
            }
    
            public virtual void PersistDeletionOf(IAggregateRoot entity)
            {
                this.DataSession.Remove((T)entity);
            }
    
            #endregion
    
        }
    }
  • 相关阅读:
    NSGA3理解(NSGA3算法及其MATLAB版本实现)
    基于分解的多目标进化优化MOEA/D之切比雪夫方法代码
    基于分解的多目标进化优化MOEA/D三种聚合函数的理解
    NSGA-II in MATLAB 源码中文注释(1)(转载)
    我的个人总结
    Unity Networking API文档翻译(二):The High Level API
    Unity Networking API文档翻译(一):Networking概述
    Unity3D独立游戏开发日记(二):摆放建筑物
    Unity3D独立游戏开发日记(一):动态生成树木
    如何申请TexturePacker
  • 原文地址:https://www.cnblogs.com/easy5weikai/p/3275285.html
Copyright © 2011-2022 走看看