Unit Of Work(工作单元)模式探索
什么是Unit Of Work模式
Unit Of Work(工作单元)模式用来维护一个由已经被业务事物修改(增加、删除或更新)的业务对象组成的列表。Unit Of Work模式负责协调这些修改的持久化工作以及所有标记的并发问题。在数据访问层中采用Unit Of Work模式带来的好处是能够确保数据完整性。如果在持久化一系列业务对象(他们属于同一个事物)的过程中出现问题,那么应该将所有的修改回滚,以确保数据始终处于有效状态。
为了演示Unit Of Work模式,使用一个简单的银行领域对两个账号之间的转账建模。下图给出了服务层(AccountService)与使用了Unit Of Work模式(以确保转账作为原子事物的Unit Of Work提交)的资源层(AccountRepository)之间的交互。
记住这张图,因为下面的代码逻辑都是依照这张图的定义来实现的。
建立Infrastructure
下面开始编写解决方案的代码,首先创建Unit Of Work模式的所有配套的基础设施代码
public interface IAggregateRoot
{
}
IAggregateRoot接口实际上属于 标记接口 ,这个接口充当了类和方法的 元数据 ,我们构建的资源库只持久化实现了IAggregateRoot接口的业务对象,所以Unit Of Work的实现将 使用IAggregateRoot接口来引用原子事物中涉及的任何业务实体 。
添加另外一个接口IUnitOfWorkRepository,这是一个用来持久化操作的接口:
public interface IUnitOfWorkRepository
{
void PersistCreationOf(IAggregateRoot entity);
void PersistUpdateOf(IAggregateRoot entity);
void PersistDeletionOf(IAggregateRoot entity);
}
之后,向Infrastructure项目中添加IUnitOfWork接口:
public interface IUnitOfWork
{
void RegisterAmended(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository);
void RegisterNew(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository);
void RegisterRemoved(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository);
void Commit();
}
值得注意的是IUnitOfWork接口在注册修改/增加/删除时需要IUnitOfWorkRepository,这样在提交时,Unit Of Work可以将真正持久化的工作委托给适当的具体实现。
最后向Infrastructure项目中添加UnitOfWork,实现IUnitOfWork:
public class UnitOfWork : IUnitOfWork
{
private Dictionary<IAggregateRoot, IUnitOfWorkRepository> addedEntities;
private Dictionary<IAggregateRoot, IUnitOfWorkRepository> changedEntities;
private Dictionary<IAggregateRoot, IUnitOfWorkRepository> deletedEntities;
public UnitOfWork()
{
addedEntities = new Dictionary<IAggregateRoot, IUnitOfWorkRepository> ();
changedEntities = new Dictionary<IAggregateRoot, IUnitOfWorkRepository> ();
deletedEntities = new Dictionary<IAggregateRoot, IUnitOfWorkRepository> ();
}
public void RegisterAmended(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository)
{
if (! changedEntities.ContainsKey(entity))
{
changedEntities.Add(entity, unitofWorkRepository);
}
}
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 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();
}
}
}
UnitOfWork类使用3个字典变量来跟踪对业务实体的代执行修改。第一个字典对应于被添加到数据存储的实体,第2个字典跟踪带更新的实体,而第三个字典处理实体删除,与字典中的实体键匹配的IUnitOfWorkRepository将被保存下来,并用于 Commit 方法之中 ,来调用Repository对象,该对象包含真正持久化实体的代码 。Commit方法遍历每一个字典,并调用相应的IUnitOfWorkRepository方法(传递实体引用)。Commit方法中的工作均被 TransactionScope 代码包装起来,如果在IUnitOfWorkRepository中执行任务时出现异常,则所有工作回滚,数据存储将保持原来的状态。
建立Model
向Model中添加一个新类Account,表示银行账户,为了方便演示简单处理了:
public class Account : IAggregateRoot
{
public decimal balance { get ; set ; }
}
为了将Accout持久化,添加IAccountRepository接口:
public interface IAccountRepository
{
void Save(Account account);
void Add(Account account);
void Remove(Account account);
}
添加AccountService服务类来协调两个账户之间的转账工作。
public class AccountService
{
private IAccountRepository _accountRepository;
private IUnitOfWork _unitOfWork;
/// <summary>
/// AccountService通过其构造器实现依赖注入
/// </summary>
/// <param name="accountRepository"></param>
/// <param name="unitOfWork"></param>
public AccountService(IAccountRepository accountRepository,
IUnitOfWork unitOfWork)
{
_accountRepository = accountRepository;
_unitOfWork = unitOfWork;
}
/// <summary>
/// 实现两个账户之间转账工作
/// </summary>
/// <param name="from"></param>
/// <param name="to"></param>
/// <param name="amount"></param>
public void Transfer(Account from , Account to, decimal amount)
{
if ( from .balance >= amount)
{
from .balance -= amount;
to.balance += amount;
_accountRepository.Save( from );
_accountRepository.Save(to);
_unitOfWork.Commit();
}
}
}
接着,它调用账户Repository来保存两个账户,最后,它调用Unit Of Work实例的Commit方法来确保该交易作为原子的Unit Of Work完成。 所以接下来的重点就是怎样Repository与Unit Of Work交互。
建立Repository来持久化业务实体
public class AccountRepository : IAccountRepository, IUnitOfWorkRepository
{
private IUnitOfWork _unitOfWork;
public AccountRepository(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public void Save(Account account)
{
_unitOfWork.RegisterAmended(account, this );
}
public void Add(Account account)
{
_unitOfWork.RegisterNew(account, this );
}
public void Remove(Account account)
{
_unitOfWork.RegisterRemoved(account, this );
}
public void PersistUpdateOf(IAggregateRoot entity)
{
// ADO.net or EF、NH来持久化
}
public void PersistCreationOf(IAggregateRoot entity)
{
// ADO.net or EF、NH来持久化
}
public void PersistDeletionOf(IAggregateRoot entity)
{
// ADO.net or EF、NH来持久化
}
}
OK,这样Unit Of Work工作模式就搭建好了, AccountRepository 实现了 IAccountRepository 和 IUnitOfWorkRepository 接口,IAccountRepository方法的实现简单地将工作委托给 Unit Of Work (传入待持久化的实体以及Repository的引用),最后,调用 Unit Of Work 类的 Commit 方法,其实是Unit Of Work引用Repository的 IUnitOfWorkRepository 的接口契约来真正完成持久化任务,至于持久化操作你可以用Ado.net或者EF、NH等。
回过头来再看这幅图,原来Unit Of Work也就是如此罢了:
本博客为 木宛城主 原创,基于 Creative Commons Attribution 2.5 China Mainland License 发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名 木宛城主 (包含链接)。如您有任何疑问或者授权方面的协商,请给我留言。
分类: Thinking In Design Pattern
作者: Leo_wl
出处: http://www.cnblogs.com/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息
查看更多关于Unit Of Work(工作单元)模式探索的详细内容...
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://haodehen.cn/did47739
Unit Of Work(工作单元)模式用来维护一个由已经被业务事物修改(增加、删除或更新)的业务对象组成的列表。Unit Of Work模式负责协调这些修改的持久化工作以及所有标记的并发问题。在数据访问层中采用Unit Of Work模式带来的好处是能够确保数据完整性。如果在持久化一系列业务对象(他们属于同一个事物)的过程中出现问题,那么应该将所有的修改回滚,以确保数据始终处于有效状态。
为了演示Unit Of Work模式,使用一个简单的银行领域对两个账号之间的转账建模。下图给出了服务层(AccountService)与使用了Unit Of Work模式(以确保转账作为原子事物的Unit Of Work提交)的资源层(AccountRepository)之间的交互。
记住这张图,因为下面的代码逻辑都是依照这张图的定义来实现的。
建立Infrastructure 下面开始编写解决方案的代码,首先创建Unit Of Work模式的所有配套的基础设施代码
public interface IAggregateRoot { }
IAggregateRoot接口实际上属于 标记接口 ,这个接口充当了类和方法的 元数据 ,我们构建的资源库只持久化实现了IAggregateRoot接口的业务对象,所以Unit Of Work的实现将 使用IAggregateRoot接口来引用原子事物中涉及的任何业务实体 。
添加另外一个接口IUnitOfWorkRepository,这是一个用来持久化操作的接口:
public interface IUnitOfWorkRepository { void PersistCreationOf(IAggregateRoot entity); void PersistUpdateOf(IAggregateRoot entity); void PersistDeletionOf(IAggregateRoot entity); }之后,向Infrastructure项目中添加IUnitOfWork接口:
public interface IUnitOfWork { void RegisterAmended(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository); void RegisterNew(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository); void RegisterRemoved(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository); void Commit(); }值得注意的是IUnitOfWork接口在注册修改/增加/删除时需要IUnitOfWorkRepository,这样在提交时,Unit Of Work可以将真正持久化的工作委托给适当的具体实现。
最后向Infrastructure项目中添加UnitOfWork,实现IUnitOfWork:
public class UnitOfWork : IUnitOfWork { private Dictionary<IAggregateRoot, IUnitOfWorkRepository> addedEntities; private Dictionary<IAggregateRoot, IUnitOfWorkRepository> changedEntities; private Dictionary<IAggregateRoot, IUnitOfWorkRepository> deletedEntities; public UnitOfWork() { addedEntities = new Dictionary<IAggregateRoot, IUnitOfWorkRepository> (); changedEntities = new Dictionary<IAggregateRoot, IUnitOfWorkRepository> (); deletedEntities = new Dictionary<IAggregateRoot, IUnitOfWorkRepository> (); } public void RegisterAmended(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository) { if (! changedEntities.ContainsKey(entity)) { changedEntities.Add(entity, unitofWorkRepository); } } 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 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(); } } }UnitOfWork类使用3个字典变量来跟踪对业务实体的代执行修改。第一个字典对应于被添加到数据存储的实体,第2个字典跟踪带更新的实体,而第三个字典处理实体删除,与字典中的实体键匹配的IUnitOfWorkRepository将被保存下来,并用于 Commit 方法之中 ,来调用Repository对象,该对象包含真正持久化实体的代码 。Commit方法遍历每一个字典,并调用相应的IUnitOfWorkRepository方法(传递实体引用)。Commit方法中的工作均被 TransactionScope 代码包装起来,如果在IUnitOfWorkRepository中执行任务时出现异常,则所有工作回滚,数据存储将保持原来的状态。
建立Model 向Model中添加一个新类Account,表示银行账户,为了方便演示简单处理了:
public class Account : IAggregateRoot
{
public decimal balance { get ; set ; }
}
为了将Accout持久化,添加IAccountRepository接口:
public interface IAccountRepository { void Save(Account account); void Add(Account account); void Remove(Account account); }添加AccountService服务类来协调两个账户之间的转账工作。
public class AccountService { private IAccountRepository _accountRepository; private IUnitOfWork _unitOfWork; /// <summary> /// AccountService通过其构造器实现依赖注入 /// </summary> /// <param name="accountRepository"></param> /// <param name="unitOfWork"></param> public AccountService(IAccountRepository accountRepository, IUnitOfWork unitOfWork) { _accountRepository = accountRepository; _unitOfWork = unitOfWork; } /// <summary> /// 实现两个账户之间转账工作 /// </summary> /// <param name="from"></param> /// <param name="to"></param> /// <param name="amount"></param> public void Transfer(Account from , Account to, decimal amount) { if ( from .balance >= amount) { from .balance -= amount; to.balance += amount; _accountRepository.Save( from ); _accountRepository.Save(to); _unitOfWork.Commit(); } } }接着,它调用账户Repository来保存两个账户,最后,它调用Unit Of Work实例的Commit方法来确保该交易作为原子的Unit Of Work完成。 所以接下来的重点就是怎样Repository与Unit Of Work交互。
建立Repository来持久化业务实体
public class AccountRepository : IAccountRepository, IUnitOfWorkRepository { private IUnitOfWork _unitOfWork; public AccountRepository(IUnitOfWork unitOfWork) { _unitOfWork = unitOfWork; } public void Save(Account account) { _unitOfWork.RegisterAmended(account, this ); } public void Add(Account account) { _unitOfWork.RegisterNew(account, this ); } public void Remove(Account account) { _unitOfWork.RegisterRemoved(account, this ); } public void PersistUpdateOf(IAggregateRoot entity) { // ADO.net or EF、NH来持久化 } public void PersistCreationOf(IAggregateRoot entity) { // ADO.net or EF、NH来持久化 } public void PersistDeletionOf(IAggregateRoot entity) { // ADO.net or EF、NH来持久化 } }OK,这样Unit Of Work工作模式就搭建好了, AccountRepository 实现了 IAccountRepository 和 IUnitOfWorkRepository 接口,IAccountRepository方法的实现简单地将工作委托给 Unit Of Work (传入待持久化的实体以及Repository的引用),最后,调用 Unit Of Work 类的 Commit 方法,其实是Unit Of Work引用Repository的 IUnitOfWorkRepository 的接口契约来真正完成持久化任务,至于持久化操作你可以用Ado.net或者EF、NH等。
回过头来再看这幅图,原来Unit Of Work也就是如此罢了:
本博客为 木宛城主 原创,基于 Creative Commons Attribution 2.5 China Mainland License 发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名 木宛城主 (包含链接)。如您有任何疑问或者授权方面的协商,请给我留言。
分类: Thinking In Design Pattern
作者: Leo_wl
出处: http://www.cnblogs.com/Leo_wl/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
版权信息查看更多关于Unit Of Work(工作单元)模式探索的详细内容...
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://haodehen.cn/did47739