回到目录

工作单元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,对于工作单元的探讨今天就先说到这里,以后肯定还是机会去研究的!

回到目录

05-11 16:04