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. 专业的GIS(电子地图、地理信息系统)在房地产行业的初步应用?

    时下随着智能手机在我国的迅猛发展以及网络时代的快速前进.手机APP以及web应用站点也顺势发展的如火如荼.我们国家还是一个人口大国,在吃穿不愁的今天,一个人口大国必需要面对的严峻问题就是住房问题.即使 ...

  2. Javascript学习3 - 语句

    原文:Javascript学习3 - 语句 javascript语句同C/C++语句相似,但也几个特殊的语句,在C/C++中没在碰到,列举在下面. 3.1 for/in 语句     可以用来遍历对象 ...

  3. SQL导入txt以及SQL中的时间格式操作

    原文:SQL导入txt以及SQL中的时间格式操作 MySQL中导入txt的指令为: load data local infile "路径名称" into table "表 ...

  4. 向西项目管理工具Maven一片

    前言 相信仅仅要做过 Java 开发的童鞋们,对 Ant 想必都不陌生,我们往往使用 Ant 来构建项目,尤其是涉及到特别繁杂的工作量.一个 build.xml 可以完毕编译.測试.打包.部署等非常多 ...

  5. 深入了解setInterval方法

    相信大家对setInterval方法肯定非常熟悉,但不少人对其缺乏深入的了解,致使当一个flash里有多个setInterval的时候就容易混淆,该清除的间隔lID没有清除,不该清除的时候却清除了.对 ...

  6. 快捷键让SublimeText在编文件快速在浏览器打开

    这里插入一下安装"view in browser"官方版的说明:(前提是得先安装package control插件) 1.通过"ctrl+shift+p"打开命 ...

  7. 无废话WCF入门教程四[WCF的配置文件]

    一.概述 配置也是WCF编程中的主要组成部分.在以往的.net应用程序中,我们会把DBConn和一些动态加载类及变量写在配置文件里.但WCF有所不同.他指定向客户端公开的服务,包括服务的地址.服务用于 ...

  8. Unity3D专访——真正的面试

    本来想写一系列的,一半的攻击,现在面试的水.人之奸,用大哥的话说,要走新手是做螺丝钉和抹布用的.还有一半是对出出学校的或者是自废武功转3d的朋友们提供一个比較有价值的參考. 只是我时间实在仓促.没有保 ...

  9. Forms身份验证和基于Role的权限验证

    Forms身份验证和基于Role的权限验证 从Membership到SimpleMembership再到ASP.NET Identity,ASP.NET每一次更换身份验证的组件,都让我更失望.Memb ...

  10. href 做导航 特效

    <div> <div> <%for (int i = 0; i < 200; i++) { %><%=i.ToString() %> <br ...