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.具体的实现思路:

图解:

UnitOfWork机制的实现和注意事项

伪代码:

(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 = ; i < 被增实体的字典.lengh; ++i )
{
实体entity tmpEntity = 被增实体的字典[i].Key;
Repository repository = 被增实体的字典[i].Value;
repository.真的增保存到数据库(tmpEntity);
} for(int i = ; i < 被删实体的字典.lengh; ++i )
{
实体entity tmpEntity = 被删实体的字典[i].Key;
Repository repository = 被删实体的字典[i].Value;
repository.真的删保存到数据库(tmpEntity);
} for(int i = ; i < 被改实体的字典.lengh; ++i )
{
实体entity tmpEntity = 被改实体的字典[i].Key;
Repository repository = 被改实体的字典[i].Value;
repository.真的改保存到数据库(tmpEntity);
}
}
}

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

IUnitOfWorkRepository.cs

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NCS.Infrastructure.Domain; namespace NCS.Infrastructure.UnitOfWork
{
/// <summary>
/// Repository实现了UnitOfWork机制的Repository
/// </summary>
public interface IUnitOfWorkRepository
{
/// <summary>
/// 实体的持久化操作(包括三个操作:增Add、删remove、改save,注意不包括查询)前,
/// 先用UnitOfWork进行登记,
/// 以便日后由UnitOfWork统一(原子性)通过Commit操作,提交修改到数据库(持久化操作)
/// </summary>
IUnitOfWork UnitOfWork { get; set; } /**
* Persist持久化系列函数
*/
void PersistCreationOf(IAggregateRoot entity);
void PersistUpdateOf(IAggregateRoot entity);
void PersistDeletionOf(IAggregateRoot entity);
}
}

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

 /*一点牢骚:
* UnitOfWork机制的蛋疼之处:
* UnitOfWork机制,决定了插入新的实体前,要预先设置数据库中的主键Id,尽管数据库自己生产主键。
* 但是,如果自己能生成主键还要数据库自动生成主键干什么,即使自己生成主键不能保证主键的唯一性,
* 除非主键是GUID。
*
* if (!addedEntities.ContainsKey(entity))
{
addedEntities.Add(entity, unitofWorkRepository);
};
* 判断实体的唯一性标准是调用实体的GetHashCode();
* public override int GetHashCode()
{
return this.Id.GetHashCode();
}
*而 this.Id是实体在数据库的主键(一般用数据库自动生成),但我插入前怎么能由我生成呢!!!
*因为:
*1.不知主键的数据库类型;
*2.即使知道主键的数据库类型,也不能因为硬编码造成的依赖,耦合。
*3.人工生成不能保证主键的唯一性,
*综上,所以就不能添加到addedEntities中,也就不能保存到数据库。
*折中的解决方案是每添加一个新的实体,就Commit一次(马上提交到数据库,并清空addedEntities)。
*
*/ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NCS.Infrastructure.Domain;
using NCS.Infrastructure.UnitOfWork;
using System.Transactions; namespace NCS.Repository.ADO
{
public class AdoUnitOfWork : IUnitOfWork
{
private Dictionary<IAggregateRoot, IUnitOfWorkRepository> addedEntities;
private Dictionary<IAggregateRoot, IUnitOfWorkRepository> changedEntities;
private Dictionary<IAggregateRoot, IUnitOfWorkRepository> deletedEntities; public AdoUnitOfWork()
{
addedEntities = new Dictionary<IAggregateRoot, IUnitOfWorkRepository>();
changedEntities = new Dictionary<IAggregateRoot, IUnitOfWorkRepository>();
deletedEntities = new Dictionary<IAggregateRoot, IUnitOfWorkRepository>();
} #region IUnitOfWork member #region 注册登记实体
public void RegisterNew(IAggregateRoot entity,
IUnitOfWorkRepository unitofWorkRepository)
{
if (!addedEntities.ContainsKey(entity))
{
addedEntities.Add(entity, unitofWorkRepository);
};
} public void RegisterRemoved(IAggregateRoot entity,
IUnitOfWorkRepository unitofWorkRepository)
{
if (!deletedEntities.ContainsKey(entity))
{
deletedEntities.Add(entity, unitofWorkRepository);
}
} public void RegisterAmended(IAggregateRoot entity,
IUnitOfWorkRepository unitofWorkRepository)
{
if (!changedEntities.ContainsKey(entity))
{
changedEntities.Add(entity, unitofWorkRepository);
}
} #endregion
public void Commit()
{
using (TransactionScope scope = new TransactionScope())
{
foreach (IAggregateRoot entity in this.addedEntities.Keys)
{
this.addedEntities[entity].PersistCreationOf(entity);
} foreach (IAggregateRoot entity in this.changedEntities.Keys)
{
this.changedEntities[entity].PersistUpdateOf(entity);
} foreach (IAggregateRoot entity in this.deletedEntities.Keys)
{
this.deletedEntities[entity].PersistDeletionOf(entity);
} scope.Complete(); this.addedEntities.Clear();
this.changedEntities.Clear();
this.deletedEntities.Clear();
}
} #endregion }
}

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 }
}
上一篇:(原)3.3 Zookeeper应用 - 负载均衡


下一篇:ios之申请后台延时执行和做一个假后台的方法(系统进入长时间后台后,再进入前台部分功能不能实现)