1.前言
疑问? 怎样保存业务的单一原子性?在学习数据库事务的时候,一直有个疑问:数据库可以对一系列操作在出现异常的时候进行回滚操作,从而保证了事务的单一原子性,那么在业务操作的时候(业务层操作)是否也可以保证业务的单一原子性呢?恰好最近在研究领域驱动模型的设计的时候,提到了Unit of Work 工作单元模式,恰好解决了我的疑问。
2. 工作单元模式
对象列表。工作单元模式负责协调这些修改的持久化工作以及所有标记的并发问题。采用工作单元模式带来的好处是能够保证数据的完整性。如果在持久化一系列业务对象的过程中出现问题,则将所有的修改回滚,以保证数据始终处于有效状态。简单来说,工作单元模式就是把业务对象的持久化由工作单元实现类进行统一管理。而不想之前那样,分布在每个具体的仓储类中,这样就可以达到一系列业务对象的统一管理,不至于在每个业务对象中出现统一的提交和回滚业务逻辑,实现代码最大化重用。
简单概括就是:对某个业务操作,比如银行的进出账的业务对象(进账对象,出账对象)进行统一管理,使它们不需要在自己的repository中提交(commit),放在工作单元中做持久化工作。
3.工作单元组成部分
3.1 IUnitofWork接口,定义持久化工作的方法,复杂维护变化的对象列表,并最后Commit,依次遍历变化的列表,并持久化,这就是Commit的事情。
public interface IUnitOfWork
{
void RegisterAdded(EntityBase entityBase, IUnitOfWorkRepository unitOfWorkRepository);
void RegisterChangeded(EntityBase entityBase, IUnitOfWorkRepository unitOfWorkRepository);
//删除操作
void RegisterRemoved(EntityBase entityBase, IUnitOfWorkRepository unitOfWorkRepository);
void Commit(); //提交操作
}
3.2 IUnitOfWorkRepository,负责持久化对象。
//持久化工作
public interface IUnitOfWorkRepository
{
void PersistNewItem(EntityBase entityBase);
void PersistUpdatedItem(EntityBase entityBase);
void PersistDeletedItem(EntityBase entityBase);
}
3.UnitOfWork 继承IUnitofWork接口,工作单元具体实现。
public class UnitOfWork:IUnitOfWork
{
#region Fields
private Dictionary<EntityBase, IUnitOfWorkRepository> addedEntities;
private Dictionary<EntityBase, IUnitOfWorkRepository> changededEntities;
private Dictionary<EntityBase, IUnitOfWorkRepository> removedEntities;
#endregion
#region Constructor
public UnitOfWork()
{
addedEntities=new Dictionary<EntityBase, IUnitOfWorkRepository>();
changededEntities=new Dictionary<EntityBase, IUnitOfWorkRepository>();
removedEntities=new Dictionary<EntityBase, IUnitOfWorkRepository>();
}
#endregion
#region Implement IUnitOfWork
public void RegisterAdded(EntityBase entityBase, IUnitOfWorkRepository unitOfWorkRepository)
{
this.addedEntities.Add(entityBase,unitOfWorkRepository);
}
public void RegisterChangeded(EntityBase entityBase, IUnitOfWorkRepository unitOfWorkRepository)
{
this.changededEntities.Add(entityBase,unitOfWorkRepository);
}
public void RegisterRemoved(EntityBase entityBase, IUnitOfWorkRepository unitOfWorkRepository)
{
this.removedEntities.Add(entityBase,unitOfWorkRepository);
}
//提交操作,在这里保存了业务的原子性操作
public void Commit()
{
using (var trans=new TransactionScope())
{
foreach (var entity in addedEntities.Keys)
{
addedEntities[entity].PersistNewItem(entity); //
}
foreach (var entity in changededEntities.Keys)
{
changededEntities[entity].PersistUpdatedItem(entity);
}
foreach (var entity in removedEntities.Keys)
{
removedEntities[entity].PersistDeletedItem(entity);
}
trans.Complete(); //提交
}
}
#endregion
}
使代码块事务。 此类不能被继承,也就是提供事务操作。TransactionScope是基于当前线程的,在当前线程中(代码块中的多个数据库操作应该在一个线程中执行,避免在多线程或是异步操作),调用Transaction.Current方法可以看到当前事务的信息.通俗易懂的讲就是在用TransactionScope 包裹的代码中统一对数据库操作进行事务管理,当执行完代码块的时候必须显示调用其commit方法提交事务,如果中途发送了异常就会自动回滚操作,原理和数据库的事务操作是一样的.
3.4 ****Repository 实现具体的IUnitOfWorkRepository接口操作,****Service服务类使用****Repository进行对象的持久化操作.
业务对象仓储实现IUnitOfWorkRepository接口的方法,PersistNewItem、PersistUpdatedItem、PersistDeletedItem 三个方法的具体内容