一、概述
工作单元是”对象-关系”行为的一种模式。维护受业务事务影响的对象列表,并协调变化的写入和并发问题的解决。——《企业应用架构模式》
1、工作单元的作用
工作单元只是将所有修改状态保存下来,在适当的时候在同一数据库连接和事务处理上下文中一次性将对象的变更提交到数据中。额外的优点是既减少了数据库调用次数,又避免数据库长事务。
同一个工作单元一般不要跨线程使用。
2、工作单元和仓储(Repository)模式
工作单元常与仓储(Repository)模式一起使用。因为多个 Repository
可能做出多处更改,如果在 Repository 中调用 DbContext.SaveChanges
或 DbContext.SaveChangesAsync
(如果使用 Entity Framework
的话),则产生了多个相互隔离开的事务。
实际上
Entity Framewok
也实现了仓储模式(DbSet<T>
)和工作单元模式(DbContext)。
3、工作单元和依赖注入(拦截器)
直接使用工作单元也是可以的。配合依赖注入和拦截器能将工作单元的创建和完成提交的工作自动化,也就是说避免了手工创建工作单元和手工调用 Complete/Commit 。这种自动化使得应对复杂业务逻辑时不用过于关注业务无关的事务安全问题。
二、基础设施
1、UnitOfWork 模块
Abp 的工作单元在 Volo.Abp.Uow 模块中实现。
1 | // File: abp\framework\src\Volo.Abp.Uow\Volo\Abp\Uow\AbpUnitOfWorkModule.cs |
把 UntiOfWork 类(见下文)在依赖容器注册服务时,会为之添加拦截器 UnitOfWorkInterceptor
,从而导致为实现类创建代理类(当然,就算不是 UnitOfwork 类但有其他拦截器,也会为实现类创建代理类)。
1 | // File: abp\framework\src\Volo.Abp.Uow\Volo\Abp\Uow\UnitOfWorkInterceptorRegistrar.cs |
2、UnitOfWork 类
如果类或类的任意方法标注了 UnitOfWorkAttribute
或类实现了 IUnitOfWorkEnabled
接口,称之为 UntiOfWork 类。
1 | // File: abp\framework\src\Volo.Abp.Uow\Volo\Abp\Uow\UnitOfWorkHelper.cs |
3、UnitOfWork 方法
什么是 UnitOfwork 方法?首先,UnitOfwork 方法一定是 UnitOfwork 类中的方法,而 UnitOfWork 类中的方法不一定是 UnitOfwork 方法。如果方法特别标注了 UnitOfWorkAttribute 则根据 UnitOfWorkAttribute 的 IsDisabled 属性判断;否则如果类型标记了 UnitOfWorkAttribute 则根据 UnitOfWorkAttribute 的 IsDisabled 属性判断;如果方法和类都没有标注 UnitOfWorkAttribute,则判断类型是否实现了 IUnitOfWorkEnabled 接口。
在类型和方法都标记了 UnitOfWorkAttribute 情况下,方法的 UnitOfWorkAttribute 优先级高一些。
1 | // File: abp\framework\src\Volo.Abp.Uow\Volo\Abp\Uow\UnitOfWorkHelper.cs |
如果方法是 UnitOfWork 方法,则应用 UnitOfWork。
1 | // File: abp\framework\src\Volo.Abp.Uow\Volo\Abp\Uow\UnitOfWorkInterceptor.cs |
三、UnitOfWork 的实现
在MyZony
的 [Abp vNext 源码分析] - 4. 工作单元 一文中,对 UnitOfWorkManager
、UnitOfWork
/ChildUnitOfWork
等类及其他基础设施已经做了足够的分析,详见该文。
参考资料
- https://uk.wikipedia.org/wiki/Unit_Of_Work
- https://aspnetboilerplate.com/Pages/Documents/Unit-Of-Work
- https://darkcraft.gitbooks.io/abpdocument2chinese/content/Abp/3.4ABP%E9%A2%86%E5%9F%9F%E5%B1%82-%E5%B7%A5%E4%BD%9C%E5%8D%95%E5%85%83.html
- https://www.jianshu.com/p/08d407669740
- https://www.cnblogs.com/myzony/p/11112288.html
- https://www.cnblogs.com/huaizuo/p/4838680.html
- https://ithelp.ithome.com.tw/articles/10157700
- https://github.com/Arch/UnitOfWork
- https://stackoverflow.com/questions/36691532/dbcontext-savechanges-method-in-unitofwork-or-in-repository-which-is-better
- https://www.cnblogs.com/wwh999/p/5458038.html