博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Thinking In Design Pattern——Unit Of Work(工作单元)模式探索
阅读量:5889 次
发布时间:2019-06-19

本文共 6123 字,大约阅读时间需要 20 分钟。

阅读目录

什么是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
addedEntities; private Dictionary
changedEntities; private Dictionary
deletedEntities; public UnitOfWork() { addedEntities = new Dictionary
(); changedEntities = new Dictionary
(); deletedEntities = new Dictionary
(); } 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;        ///         /// AccountService通过其构造器实现依赖注入        ///         ///         ///         public AccountService(IAccountRepository accountRepository,                              IUnitOfWork unitOfWork)        {            _accountRepository = accountRepository;            _unitOfWork = unitOfWork;                    }        ///         /// 实现两个账户之间转账工作        ///         ///         ///         ///         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实现了IAccountRepositoryIUnitOfWorkRepository接口,IAccountRepository方法的实现简单地将工作委托给Unit Of Work(传入待持久化的实体以及Repository的引用),最后,调用Unit Of Work类的Commit方法,其实是Unit Of Work引用Repository的IUnitOfWorkRepository的接口契约来真正完成持久化任务,至于持久化操作你可以用Ado.net或者EF、NH等。

回过头来再看这幅图,原来Unit Of Work也就是如此罢了:

本博客为 原创,基于 发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名 (包含链接)。如您有任何疑问或者授权方面的协商,请给我留言。
分类:
本文转自木宛城主博客园博客,原文链接:http://www.cnblogs.com/OceanEyes/archive/2012/10/29/UnitOfWork--ByEyes.html,如需转载请自行联系原作者
你可能感兴趣的文章
12-18Windows窗体应用小程序之记事本(1)
查看>>
02-18 报表
查看>>
毕业论文一次性修改所有字母和数字的字体
查看>>
结构体:HASH表模板
查看>>
[转]理解Linux文件系统之inode
查看>>
在i3 Cpu上允许64位系统
查看>>
视频编解码学习之五:差错控制及传输
查看>>
String:自动进行空间扩展
查看>>
Postman教程
查看>>
python模块--os模块
查看>>
HSSFRow获取单元格方法与区别
查看>>
《图解HTTP》读书笔记
查看>>
iOS开发-单例模式
查看>>
词汇小助手V1.2——可以显示英语单词的国际音标
查看>>
洛谷 1365 WJMZBMR打osu! / Easy
查看>>
删除UINavigationItem上的BarButtonItem
查看>>
数据分析相关模块
查看>>
Python数据结构1-----基本数据结构和collections系列
查看>>
SQL Denali-FileTable
查看>>
C# 图像处理:复制屏幕到内存中,拷屏操作
查看>>