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

    }
}

 

 

 

 

posted @ 2013-08-22 17:04  easy5  阅读(782)  评论(0编辑  收藏  举报