在DDD开发过程中,一个良好的Uow设计必不可少,我心目中的Uow设计应该具备以下几点:

1、有着良好的抽象,有着恰如其分的命名;

2、能够应付不同的组件,比如你的系统中可能会存在EfUnitOfWork、RedisUnitOfWork;

3、易于使用,不用开发者显示调用。Uow在一个用户请求开始到结束能够自动包裹在业务逻辑外边;

在阅读了Abp的源码后我感觉Abp中的Uow正好符合我这几点要求,但是其实现稍有点复杂,例如在EfUnitOfWork中加入了DynamicFilters,EfUnitOfWork支持多DbContext,这些复杂性导致EfUnitOfWork类变得有点臃肿。所以我在实例代码中移除了这些设计。

一、业务抽象

一个使用Uow的典型代码片段如下:

            using (var uow = UowManager.Begin())
{
//....logic uow.Commit();
}

从这段代码中我们基本可以分析出下面的Uow抽象。

1、IUnitOfWorkManager

从上面的代码片段可以看出,此Manager应该具有一个Begin()方法,返回IDisposable类型。

2、IUnitOfWorkCompleteHandle

IUnitOfWorkManager的Begin()方法返回的IDisposable类型应该具有Commit()的能力,该抽象用于对IUnitOfWork的提交和释放资源。

3、IUnitOfWork

从这个代码片段中我们并没有看到IUnitOfWork这个抽象,原因在于IUnitOfWorkManager隐藏了具体的IUnitOfWork,IUnitOfWorkManager.Begin()实现中实际上是具体的IUnitOfWork.Begin()调用。

4、ICurrentUnitOfWorkProvider

针对用户在一次上下文中的请求,具有唯一的一个IUnitOfWork,因此可以在任意时刻通过ICurrentUnitOfWorkProvider来读取当前上下文的IUnitOfWork。

通过接口命名描述就能理清整个Uow设计思路:

二、EfUnitOfWork

EfUnitOfWork的Begin体现在对TransactionScope的调用、Commit体现在对dbContext.SaveChanges()的调用

        public void Begin(UnitOfWorkOptions options)
{
_transactionScope = new TransactionScope(
options.TransactionScopeOption.GetValueOrDefault(_defaultUnitOfWorkOptions.TransactionScopeOption),
new TransactionOptions()
{
IsolationLevel = options.IsolationLevel.GetValueOrDefault(_defaultUnitOfWorkOptions.IsolationLevel),
Timeout = options.Timeout.GetValueOrDefault(_defaultUnitOfWorkOptions.Timeout)
});
}
        public void Complete()
{
try
{
_dbContext.SaveChanges();
_transactionScope?.Complete(); _completed?.Invoke();
}
catch
{
_failed?.Invoke();
throw;
} }

三、通过Castle实现Aop,将Uow包裹ApplicationService层

定义UnitOfWorkInterceptor,该拦截器表现为要对现有的一个方法包裹UnitOfWork实现。

        private void PerformUow(IInvocation invocation, UnitOfWorkOptions options)
{
using (var uow = _unitOfWorkManager.Begin(options))
{
invocation.Proceed();
uow.Complete();
}
}

四、缺陷

该方案是一个很优秀的UnitOfWork设计,不过当我们在使用DDD模型时如果引申出了领域事件,该方案则不够理想。当领域模型未能够正确持久化时则不应该发布领域事件。针对这一要求我有两个想法:

1、将发布领域事件注册在UnitOfWorkManager的Completed阶段,确保EfUnitOfWork正确执行后再发布领域事件;

2、抽象出EfUnitOfWorkParticipant、IServiceBusParticipant。在Commit阶段分别Commit这两个participant,有一个失败则Rollback所有的participant。

具体实现请参考:https://git.oschina.net/richieyangs/BookLibrary.git

Unit Of Work的设计的更多相关文章

  1. FocusBI: 使用Python爬虫为BI准备数据源(原创)

    关注微信公众号:FocusBI 查看更多文章:加QQ群:808774277 获取学习资料和一起探讨问题. <商业智能教程>pdf下载地址 链接:https://pan.baidu.com/ ...

  2. DynamIQ扫盲文

    综述: ARM CPU的架构都基于big.LITTLE大小核技术.而再big.LITTLE的基础上,又添加了DynamIQ.单一Cluster中可以又8个core,且支持不同架构的core,以及支持不 ...

  3. [.NET领域驱动设计实战系列]专题四:前期准备之工作单元模式(Unit Of Work)

    一.前言 在前一专题中介绍了规约模式的实现,然后在仓储实现中,经常会涉及工作单元模式的实现.然而,在我的网上书店案例中也将引入工作单元模式,所以本专题将详细介绍下该模式,为后面案例的实现做一个铺垫. ...

  4. 基于Netty打造RPC服务器设计经验谈

    自从在园子里,发表了两篇如何基于Netty构建RPC服务器的文章:谈谈如何使用Netty开发实现高性能的RPC服务器.Netty实现高性能RPC服务器优化篇之消息序列化 之后,收到了很多同行.园友们热 ...

  5. 初探领域驱动设计(2)Repository在DDD中的应用

    概述 上一篇我们算是粗略的介绍了一下DDD,我们提到了实体.值类型和领域服务,也稍微讲到了DDD中的分层结构.但这只能算是一个很简单的介绍,并且我们在上篇的末尾还留下了一些问题,其中大家讨论比较多的, ...

  6. 关于领域驱动设计(DDD)中聚合设计的一些思考

    关于DDD的理论知识总结,可参考这篇文章. DDD社区官网上一篇关于聚合设计的几个原则的简单讨论: 文章地址:http://dddcommunity.org/library/vernon_2011/, ...

  7. [.NET领域驱动设计实战系列]专题二:结合领域驱动设计的面向服务架构来搭建网上书店

    一.前言 在前面专题一中,我已经介绍了我写这系列文章的初衷了.由于dax.net中的DDD框架和Byteart Retail案例并没有对其形成过程做一步步分析,而是把整个DDD的实现案例展现给我们,这 ...

  8. 电商系统中的商品模型的分析与设计—续

    前言     在<电商系统中的商品模型的分析与设计>中,对电商系统商品模型有一个粗浅的描述,后来有博友对货品和商品的区别以及属性有一些疑问.我也对此做一些研究,再次简单的对商品模型做一个介 ...

  9. 我的“第一次”,就这样没了:DDD(领域驱动设计)理论结合实践

    写在前面 插一句:本人超爱落网-<平凡的世界>这一期,分享给大家. 阅读目录: 关于DDD 前期分析 框架搭建 代码实现 开源-发布 后记 第一次听你,清风吹送,田野短笛:第一次看你,半弯 ...

随机推荐

  1. FREERTOS 手册阅读笔记

    郑重声明,版权所有! 转载需说明. FREERTOS堆栈大小的单位是word,不是byte. 根据处理器架构优化系统的任务优先级不能超过32,If the architecture optimized ...

  2. .NET平台开源项目速览(18)C#平台JSON实体类生成器JSON C# Class Generator

    去年,我在一篇文章用原始方法解析复杂字符串,json一定要用JsonMapper么?中介绍了简单的JSON解析的问题,那种方法在当时的环境是非常方便的,因为不需要生成实体类,结构很容易解析.但随着业务 ...

  3. 自己实现一个javascript事件模块

    nodejs中的事件模块 nodejs中有一个events模块,用来给别的函数对象提供绑定事件.触发事件的能力.这个别的函数的对象,我把它叫做事件宿主对象(非权威叫法),其原理是把宿主函数的原型链指向 ...

  4. SDWebImage源码解读 之 SDWebImageCompat

    第三篇 前言 本篇主要解读SDWebImage的配置文件.正如compat的定义,该配置文件主要是兼容Apple的其他设备.也许我们真实的开发平台只有一个,但考虑各个平台的兼容性,对于框架有着很重要的 ...

  5. android studio你可能忽视的细节——启动白屏?drawable和mipmap出现的意义?这里都有!!!

    android studio用了很久了,也不知道各位小伙伴有没有还在用eclipse的,如果还有,楼主真心推荐转到android studio来吧,毕竟亲儿子,你会知道除了启动速度稍微慢些,你找不到一 ...

  6. java设计模式之--单例模式

    前言:最近看完<java多线程编程核心技术>一书后,对第六章的单例模式和多线程这章颇有兴趣,我知道我看完书还是记不住多少的,写篇博客记录自己所学的只是还是很有必要的,学习贵在坚持. 单例模 ...

  7. Asp.Net Core + Dapper + Repository 模式 + TDD 学习笔记

    0x00 前言 之前一直使用的是 EF ,做了一个简单的小项目后发现 EF 的表现并不是很好,就比如联表查询,因为现在的 EF Core 也没有啥好用的分析工具,所以也不知道该怎么写 Linq 生成出 ...

  8. 根据ip判断返回城市名称查询当地天气

    <?phpheader("content-type:text/html;charset=utf-8");date_default_timezone_set("Asi ...

  9. SAP CRM 用户界面对象类型和设计对象

    在CRM中的用户界面对象类型的帮助下,我们可以做这些工作: 进行不同的视图配置 创建动态导航 从设计层控制字段标签.值帮助 控制BOL对象的属性的可视性 从导航栏访问自定义组件 一个用户界面对象类型之 ...

  10. Android 中的mvvm

    我们来了解一下MVVM模式与Databinding ,MVVM是一种模式,Databinding 是一种框架.DataBinding是一个实现数据和UI绑定的框架.而ViewModel和View可以通 ...