Unit Of Work-工作单元

阅读目录:

掀起了你的盖头来,让我看你的眼睛,你的眼睛明又亮呀,好像那水波一模样;掀起了你的盖头来,让我看你的脸儿,看看你的脸儿红又圆呀,好像那苹果到秋天。。。

  Hi,Unit Of Work,掀起你的盖头来,原来 You are so beautiful !

概念中的理解

Unit Of Work:维护受业务事务影响的对象列表,并协调变化的写入和并发问题的解决。即管理对象的CRUD操作,以及相应的事务与并发问题等。Unit of Work是用来解决领域模型存储和变更工作,而这些数据层业务并不属于领域模型本身具有的。

  关于Unit Of Work的更多详情,请查看:http://martinfowler.com/eaaCatalog/unitOfWork.html,Unit Of Work中的“Unit”是单元的意思,知道单元测试的朋友都知道其也包含“Unit”单词,但是是一个意思吗?Unit Test(单元测试)虽然也包含“Unit”这个单词,但是意义并不是一样,单元测试中的“Unit”可以看做是最小单元,比如组装飞机的最小零部件,但是Unit Of Work(工作单元)并非无此,注意后面“Work”单词,意思是可以“工作”的单元,比如一场篮球比赛需要两个队,10名上场球员参与,这样完成的“动作”才会称之为篮球比赛,也就是“工作单元”,一个篮球队或是一个篮球队员并不能完成或称为篮球比赛,但是这个工作的"单元"也只是相对而言,比如上篮动作就只需要一个篮球队员就可以完成,那这个篮球队员就可以看做是“工作单元”。需要注意的是,Unit中可以包含很多“动作”,可以是一个也可以是多个,比如上面的例子,如果“单元”中包含对于多个动作,那这个“单元”中所有的动作都是“内聚”的,脱离这个“单元”这个动作就没有意义了,比如篮球比赛中的一次吹罚,当然这只是字面上理解的意思,也只是我个人的一些看法,希望看到着没有被我忽悠到。

  扯了一些不沾边的东西,我们再看一个现实中例子,也最能说明Unit Of Work所包含的意思,就是银行转账操作,包含两个动作:转出方扣钱和转入方加钱,这两个动作要么都完成,要么都不完成,也就是事务操作,完成就Commit(提交),完不成就Rollback(回滚)。

  回到Unit Of Work的定义,Unit of Work是用来解决领域模型存储和变更工作,在ORM进行持久化的时候,比如Entity Framework的SaveChanges操作,其实就可以看做是Unit Of Work,也就是定义中所说“用来解决领域模型存储和变更工作”,但是如果项目是基于Entity Framework进行DDD(领域驱动设计)开发设计的,那Entity Framework中的Domain Model就必然包含业务逻辑,这就不符合“而这些数据层业务并不属于领域模型本身具有的”,也就是说Unit Of Work必须独立于Domain Layer(领域层),注意独立的业务是“数据层”业务,并不是业务场景中的“业务”,比如“转账业务”,转出方扣钱和转入方加钱这个业务就属于“数据层业务”,有的人会把Unit Of Work放在Domain Layer(领域层)中,其实是有些不恰当的,应该是放在Infrastructure Layer(基础层)中,但其实也只是相对而言,如果涉及到具体的业务单元模块,具体实现可以放在领域层中。

  在DDD(领域驱动设计)开发设计中,Unit Of Work的使用一般会结合Repository(仓储)使用,有关Repository可以参阅dudu的一篇文章:http://www.cnblogs.com/dudu/archive/2011/05/25/repository_pattern.html,文中的解释很清楚直白:

Repository:是一个独立的层,介于领域层与数据映射层(数据访问层)之间。它的存在让领域层感觉不到数据访问层的存在,它提供一个类似集合的接口提供给领域层进行领域对象的访问。Repository是仓库管理员,领域层需要什么东西只需告诉仓库管理员,由仓库管理员把东西拿给它,并不需要知道东西实际放在哪。

  Unit Of Work所做的工作可以看做是收集Repository出入库的“商品”,便于一次装车,运输过程中如果没有出现问题,那这车的所有“商品”就安全到达,如果出现问题,那这车的所有“商品”全部打回,这辆车就是“单元”的意思。

  关于Repository和Unit Of Work的关系,简单画了个示意图:

                点击查看大图

代码中的实现

  关于Unit Of Work项目中的应用,可以参照dax.net的Byteart Retail项目,本人现在也正在学习中,项目是基于DDD设计实现的,下面是IUnitOfWork的示例代码:

 1 namespace ByteartRetail.Domain
2 {
3 /// <summary>
4 /// 表示所有集成于该接口的类型都是Unit Of Work的一种实现。
5 /// </summary>
6 /// <remarks>有关Unit Of Work的详细信息,请参见UnitOfWork模式:http://martinfowler.com/eaaCatalog/unitOfWork.html。
7 /// </remarks>
8 public interface IUnitOfWork
9 {
10 /// <summary>
11 /// 获得一个<see cref="System.Boolean"/>值,该值表述了当前的Unit Of Work事务是否已被提交。
12 /// </summary>
13 bool Committed { get; }
14 /// <summary>
15 /// 提交当前的Unit Of Work事务。
16 /// </summary>
17 void Commit();
18 /// <summary>
19 /// 回滚当前的Unit Of Work事务。
20 /// </summary>
21 void Rollback();
22 }
23 }

  根据UnitOfWork中的概念描述“这些数据层业务并不属于领域模型本身具有的”,所以IUnitOfWork放在Infrastructure Layer(应用层),其实IUnitOfWork的具体管理实现是放在领域层的,但不会放在Domain Model(领域模型)中,具体的数据层业务会结合Repository,也就是说IUnitOfWork会贯彻所有的Repository实现,因为它要对所有仓储的的持久化做统一管理:

 1     /// <summary>
2 /// Represents that the implemented classes are repository contexts.
3 /// </summary>
4 public interface IRepositoryContext : IUnitOfWork, IDisposable
5 {
6 /// <summary>
7 /// Gets the unique-identifier of the repository context.
8 /// </summary>
9 Guid ID { get; }
10 /// <summary>
11 /// Registers a new object to the repository context.
12 /// </summary>
13 /// <typeparam name="TAggregateRoot">The type of the aggregate root.</typeparam>
14 /// <param name="obj">The object to be registered.</param>
15 void RegisterNew<TAggregateRoot>(TAggregateRoot obj)
16 where TAggregateRoot : class, IAggregateRoot;
17 /// <summary>
18 /// Registers a modified object to the repository context.
19 /// </summary>
20 /// <typeparam name="TAggregateRoot">The type of the aggregate root.</typeparam>
21 /// <param name="obj">The object to be registered.</param>
22 void RegisterModified<TAggregateRoot>(TAggregateRoot obj)
23 where TAggregateRoot : class, IAggregateRoot;
24 /// <summary>
25 /// Registers a deleted object to the repository context.
26 /// </summary>
27 /// <typeparam name="TAggregateRoot">The type of the aggregate root.</typeparam>
28 /// <param name="obj">The object to be registered.</param>
29 void RegisterDeleted<TAggregateRoot>(TAggregateRoot obj)
30 where TAggregateRoot : class, IAggregateRoot;
31 }

  UnitOfWork的具体操作会在EntityFrameworkRepositoryContext中完成,并在EntityFrameworkRepository中注册IEntityFrameworkRepositoryContext接口类型映射,EntityFrameworkRepository作用就是在Repository集合中去完成持久化,工作单元的持久化,看下EntityFrameworkRepositoryContext中的示例代码:

 1 using System.Data.Entity;
2 using System.Threading;
3
4 namespace ByteartRetail.Domain.Repositories.EntityFramework
5 {
6 public class EntityFrameworkRepositoryContext : RepositoryContext, IEntityFrameworkRepositoryContext
7 {
8 private readonly ThreadLocal<ByteartRetailDbContext> localCtx = new ThreadLocal<ByteartRetailDbContext>(() => new ByteartRetailDbContext());
9
10 public override void RegisterDeleted<TAggregateRoot>(TAggregateRoot obj)
11 {
12 localCtx.Value.Entry<TAggregateRoot>(obj).State = System.Data.EntityState.Deleted;
13 Committed = false;
14 }
15
16 public override void RegisterModified<TAggregateRoot>(TAggregateRoot obj)
17 {
18 localCtx.Value.Entry<TAggregateRoot>(obj).State = System.Data.EntityState.Modified;
19 Committed = false;
20 }
21
22 public override void RegisterNew<TAggregateRoot>(TAggregateRoot obj)
23 {
24 localCtx.Value.Entry<TAggregateRoot>(obj).State = System.Data.EntityState.Added;
25 Committed = false;
26 }
27
28 public override void Commit()
29 {
30 if (!Committed)
31 {
32 localCtx.Value.SaveChanges();
33 Committed = true;
34 }
35 }
36
37 public override void Rollback()
38 {
39 Committed = false;
40 }
41
42 protected override void Dispose(bool disposing)
43 {
44 if (disposing)
45 {
46 if (!Committed)
47 Commit();
48 localCtx.Value.Dispose();
49 localCtx.Dispose();
50 base.Dispose(disposing);
51 }
52 }
53
54 #region IEntityFrameworkRepositoryContext Members
55
56 public DbContext Context
57 {
58 get { return localCtx.Value; }
59 }
60
61 #endregion
62 }
63 }

  UnitOfWork的操作会贯彻所有Repository的持久化,在Byteart Retail项目中的领域层,有很多的类和接口关联,比如IEntity、IAggregateRoot、IRepository、IRepositoryContext、Repository、RepositoryContext、EntityFrameworkRepositoryContext等等,用类图表示有时候不太直观,画了一个简单的示例图,方便理解UnitOfWork在DDD中的应用始末:

点击查看大图

  左半部分:IEntity、IAggreateRoot、IRepository<TAggregateRoot>、Repository<TAggregateRoot>等,可以看做是仓储库,和领域模型相关(存在于领域层),右半部:IUnitOfWork、IRepositoryContext、RepositoryContext、IEntityFrameworkRepositoryContext等,可以看做是仓储的持久化(工作单元),这两者通过EntityFrameworkRepository进行IoC注册对象,完成所有Repository的整个工作单元的协调、管理。

后记

  You don't know you're beautiful,that's what makes you beautiful ! -你不知道你是如此的美丽动人,这就是你美丽动人的所在!

  如果你觉得本篇文章对你有所帮助,请点击右下部“推荐”,^_^

  参考资料:

Unit Of Work-工作单元的更多相关文章

  1. ABP(现代ASP.NET样板开发框架)系列之12、ABP领域层——工作单元(Unit Of work)

    点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之12.ABP领域层——工作单元(Unit Of work) ABP是“ASP.NET Boilerplate Pr ...

  2. ABP领域层——工作单元(Unit Of work)

    ABP领域层——工作单元(Unit Of work) 点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之12.ABP领域层——工作单元(Unit Of work) ...

  3. 解析ABP框架中的事务处理和工作单元,ABP事务处理

    通用连接和事务管理方法连接和事务管理是使用数据库的应用程序最重要的概念之一.当你开启一个数据库连接,什么时候开始事务,如何释放连接...诸如此类的. 正如大家都知道的,.Net使用连接池(connec ...

  4. [Abp 源码分析]六、工作单元的实现

    0.简介 在 Abp 框架内部实现了工作单元,在这里讲解一下,什么是工作单元? Unit Of Work(工作单元)模式用来维护一个由已经被业务事物修改(增加.删除或更新)的业务对象组成的列表.Uni ...

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

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

  6. 换个角度说工作单元(Unit Of Work):创建、持有与API调用

    看到一些工作单元的介绍,有两种感觉,第一种是很学院,说了等于没说,我估计很多都是没有自己引入到实际的项目中去,第二种是告诉我一种结果,说这就是工作单元,但是没说为什么要这么使用.所以,本篇想要探讨的是 ...

  7. 工作单元(Unit of Work)

    维护受业务事务影响的对象列表,并协调变化的写入和并发问题的解决. 从DB中存取Data时,必须记录增删改动作,以将对DB有影响的数据写会到DB中去. 如果在每次修改对象模型时就对DB进行相应的修改,会 ...

  8. ABP理论学习之工作单元(Unit of Work)

    返回总目录 本篇目录 公共连接和事务管理方法 ABP中的连接和事务管理 仓储类 应用服务 工作单元 工作单元详解 关闭工作单元 非事务的工作单元 工作单元方法调用其它 工作单元作用域 自动保存 IRe ...

  9. 基于DDD的.NET开发框架 - ABP工作单元(Unit of Work)

    返回ABP系列 ABP是“ASP.NET Boilerplate Project (ASP.NET样板项目)”的简称. ASP.NET Boilerplate是一个用最佳实践和流行技术开发现代WEB应 ...

  10. 【.Net设计模式系列】工作单元(Unit Of Work)模式 ( 二 )

    回顾 在上一篇博客[.Net设计模式系列]仓储(Repository)模式 ( 一 ) 中,通过各位兄台的评论中,可以看出在设计上还有很多的问题,在这里特别感谢 @横竖都溢 @ 浮云飞梦 2位兄台对博 ...

随机推荐

  1. Android - 采用ApiDemos得知Android开展

    采用ApiDemos得知Android开展 本文地址: http://blog.csdn.net/caroline_wendy 位置: android-sdk/samples/android-20/l ...

  2. 好记性不如烂笔头85-spring3学习(6)-BeanFactory 于bean生命周期

    假设BeanFactory为了产生.管理Bean, 一个Bean从成立到毁灭.它会经过几个阶段运行. 据我所知,一般bean包括在生命周期:设定,初始化,使用阶段,四个核心阶段销毁. 1.@Bean的 ...

  3. jvm对大对象分配内存的特殊处理(转)

    前段日子在和leader交流技术的时候,偶然听到jvm在分配内存空间给大对象时,如果young区空间不足会直接在old区切一块过去.对于这个结论很好奇,也比较怀疑,所以就上网搜了下,发现还真有这么回事 ...

  4. T4模板使用技巧

    =============C#.Net 篇目录============== 示例代码:示例代码__你必须懂的T4模板:浅入深出.rar (一)什么是T4模板? T4,即4个T开头的英文字母组合:Tex ...

  5. C#-简单的定时器(C# ConsoleApp) ---ShinePans

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2hpbmVwYW4=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA ...

  6. MongoDB详解学习历程

    MongoDB是一个基于分布式文件存储的数据库,它是介于关系数据库和非关系数据库之间的产品. MongoDB支持的数据结构非常松散,类似json的bjson格式,因此可以存储比较复杂的数据类型.Mon ...

  7. 一个JavaWeb项目开发总结

    一.学会如何读一个JavaWeb项目源代码 步骤:表结构->web.xml->mvc->db->spring ioc->log->代码 先了解项目数据库的表结构,这 ...

  8. pig 的chararry不能用于比较的类型可以comparison operator

    pig 的chararry类型可以是由场,通过现场实地比较. element_id 这是chararray种类. 声明: no_app_category_mapping = filter no_ele ...

  9. 搭建一个BS 的简单SOA 架构(直接通过jquery 调用后台的 wcf 服务的架构)(第一天)

    亲们!还在用传统的三层架构吗?你还在对SOA架构 不了解吗? 那就赶快来学习下一个 比较简单的SOA的架构吧!我会手把手的 教会你们怎么搭建这个 简单的SOA的架构. 其中用的技术点保证  WCF,a ...

  10. Lua的多任务机制——协程(coroutine)

    并发是现实世界的本质特征,而聪明的计算机科学家用来模拟并发的技术手段便是多任务机制.大致上有这么两种多任务技术,一种是抢占式多任务(preemptive multitasking),它让操作系统来决定 ...