回顾

  上一篇我们根据工作单元的原理基于ADO.NET进行了简单的实现,但是当项目需求发生变化的时候,比如需要引入ORM框架又要兼容当前ADO.NET实现的方式时,先前的实现就无法满足这个需求了。

  话就不多说了,我们就跟据当前的需求变化来重构工作单元吧。

重构UnitOfWork

  首先我们看看原先实现的工作单元提取出来的接口,代码如下:

public interface IUnitOfWork
{
void RegisterAdd(string sql, params IDataParameter[] parameters);
void RegisterSave(string sql, params IDataParameter[] parameters);
void RegisterRemove(string sql, params IDataParameter[] parameters);
void Comit();
}

  由于需求需要兼容ORM和ADO.NET方式,而以上的接口仅仅支持ADO.NET的方式,因此接口需要改变,例如:

//其他代码省略
void RegisterAdd(object entity);

  观察以上的修改会发现如果要满足需求,则需要判断是ADO.NET或者是ORM的操作,那么就有了两种不同的职责,这显然是不合理的,但是如果我们将ADO.NET和ORM还是让对应的数据层类去实现的话,就符合单一责任了,于是经过以上分析,就可以对以上的接口做进一步的修改了,大致代码如下:

//其他代码省略
void RegisterAdd(object entity, IUnitOfWorkRepository repository);

  按照这个思路的话,这个IUnitOfWorkRepository的方法数量则会跟IUnitOfWork基本相同(没有Commit),一个是注册,而另一个则是实际的操作,因此接口代码则会跟第一次改为object的相同了,代码如下:

public interface IUnitOfWorkRepository
{
void ExecuteAdd(object entity);
void ExecuteSave(object entity);
void ExecuteRemove(object entity);
}

  有了以上的改变之后,就可以实现IUnitOfWork了,代码结构上还是跟SQLUnitOfWork类似的,差别是原先是使用一个List<SQLEntity>来存储所有的CUD操作,但是现在必须要区分出不同类型的操作,因此需要有分别存储CUD的容器,大致代码如下:

public class UnitOfWork : IUnitOfWork
{
private Dictionary<object, IUnitOfWorkRepository> m_addList =
new Dictionary<object, IUnitOfWorkRepository>();
private Dictionary<object, IUnitOfWorkRepository> m_saveList =
new Dictionary<object, IUnitOfWorkRepository>();
private Dictionary<object, IUnitOfWorkRepository> m_removeList =
new Dictionary<object, IUnitOfWorkRepository>(); public void RegisterAdd(object entity, IUnitOfWorkRepository repository)
{
if (!this.m_addList.ContainsKey(entity))
this.m_addList.Add(entity, repository);
} public void RegisterSave(object entity, IUnitOfWorkRepository repository)
{
if (!this.m_saveList.ContainsKey(entity))
this.m_saveList.Add(entity, repository);
} public void RegisterRemove(object entity, IUnitOfWorkRepository repository)
{
if (!this.m_removeList.ContainsKey(entity))
this.m_removeList.Add(entity, repository);
} public void Commit()
{
using (TransactionScope trans = new TransactionScope())
{
foreach (var entity in this.m_addList.Keys)
{
this.m_addList[entity].ExecuteAdd(entity);
} foreach (var entity in this.m_saveList.Keys)
{
this.m_saveList[entity].ExecuteSave(entity);
} foreach (var entity in this.m_removeList.Keys)
{
this.m_removeList[entity].ExecuteRemove(entity);
}
trans.Complete();
}
}
}

  到这里我们就将工作单元重构工作完成了,接下来就可以根据IUnitOfWorkRepository派生出基于ADO.NET和ORM的实现了。

重构SchoolRepository

  首先我们先看一下重构后的代码:

class SchoolRepository : IRepository, IUnitOfWorkRepository
{
private IDbConnection m_connection = null;
private IUnitOfWork m_uow = null; public SchoolRepository(IDbConnection connection, IUnitOfWork uow)
{
this.m_connection = connection;
this.m_uow = uow;
} public void Add(object entity)
{
this.m_uow.RegisterAdd(entity, this);
} public void Save(object entity)
{
this.m_uow.RegisterSave(entity, this);
} public void Remove(object entity)
{
this.m_uow.RegisterRemove(entity, this);
} public void ExecuteAdd(object entity)
{
School school = entity as School;
using (IDbCommand cmd = this.m_connection.CreateCommand())
{
cmd.CommandType = CommandType.Text;
cmd.CommandText = "insert school values(@id, @name)";
cmd.Parameters.Add(new SqlParameter("@id", school.Id));
cmd.Parameters.Add(new SqlParameter("@name", school.Name));
cmd.ExecuteNonQuery();
}
} public void ExecuteSave(object entity)
{
//代码略
} public void ExecuteRemove(object entity)
{
//代码略
}
}

  IRepository是数据层的基础接口,从代码中我们看到原先CUD的方法被拆分到了CUD和ExecuteXXX方法中去了,CUD方法负责调用IUnitOfWork的接口,而ExecuteXXX则实现具体的数据库操作

基于NHibernate的IUnitOfWorkRepository实现

  先看代码吧

class SchoolRepository : IRepository, IUnitOfWorkRepository
{
private IUnitOfWork m_uow = null; public SchoolRepository(IDbConnection connection, IUnitOfWork uow)
{
this.m_uow = uow;
} public void Add(object entity)
{
this.m_uow.RegisterAdd(entity, this);
} public void Save(object entity)
{
this.m_uow.RegisterSave(entity, this);
} public void Remove(object entity)
{
this.m_uow.RegisterRemove(entity, this);
} public void ExecuteAdd(object entity)
{
SessionFactory.CurrentSession.Add(entity);
} public void ExecuteSave(object entity)
{
//代码略
} public void ExecuteRemove(object entity)
{
//代码略
}
}

  从基于NHibernate的实现中,我们可以看到ExecuteXXX的方法都是去调用NHibernateSession的相关方法的。

结尾

  到此数据层就只差查询了,下次会分享一下关于查询的模式。

  文章到这里就结束了,如果有什么问题和错误欢迎留言,谢谢!

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)模式 ( 二 )

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

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

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

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

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

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

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

  9. 工作单元(Unit of Work)

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

随机推荐

  1. 【Android】Android内存机制,了解Android堆和栈

    1.dalvik的Heap和Stack 这里说的只是dalvik java部分的内存,实际上除了dalvik部分,还有native.     下面针对上面列出的数据类型进行说明,只有了解了我们申请的数 ...

  2. Python之Web框架们

    Python的WEB框架 Bottle Bottle是一个快速.简洁.轻量级的基于WSIG的微型Web框架,此框架只由一个 .py 文件,除了Python的标准库外,其不依赖任何其他模块. pip i ...

  3. FreeCodeCamp 高级算法(个人向)

    freecodecamp 高级算法地址戳这里. freecodecamp的初级和中级算法,基本给个思路就能完成,而高级算法稍微麻烦了一点,所以我会把自己的解答思路写清楚,如果有错误或者更好的解法,欢迎 ...

  4. 如何将Scrapy 部署到Scrapyd上?

    安装上传工具 1.上传工具 scrapyd-client 2.安装方法: pip install scrapyd-client 3.上传方法: python d:\Python27\Scripts\s ...

  5. asp.net“服务器应用程序不可用” 解决方法

    服务器应用程序不可用 您试图在此 Web 服务器上访问的 Web 应用程序当前不可用.请点击 Web 浏览器中的“刷新”按钮重试您的请求. 管理员注意事项: 详述此特定请求失败原因的错误消息可在 We ...

  6. Java 周历日历

    WeekCalendarUtils工具类代码,传入起始日期即可返回对应日期的周历日历,年月部分添加周数统计 import java.util.Calendar; import java.util.Da ...

  7. AutoCAD2007专业版

    07版的AutoCAD应该是一个很经典的版本了,点此下载,附带破解注册机和天正的插件包,可以查看天正软件画的图纸. AutoCAD2007本身没有标签工具,切换窗口很不方便,如果能配合多标签插件Doc ...

  8. Spring 4.3.2+quartz2.2.3单机、集群+websocket集群实现文本或图片推送、接收及显示

    相关环境 Nginx,Spring4.x当前(要选择4.0+),tomcat8.x,Quartz 2.x集群 测试面页:http://sms.reyo.cn/socket.html 测试面页是文本和图 ...

  9. [Android] 转移“植物大战僵尸2”存档的办法,无需root

    作者:zyl910 查过了很多文章,都说需要root后才能转移存档.但很多时候是不能root的,此时该怎么办呢? 我研究了很久,最终找到了一种办法,无需root也能转移存档. 一.备份 我用的是联想手 ...

  10. Spring和cxf3的整合,以maven的方式

    一.引入cxf3 我这里使用的是最新的版本cxf3.1.8 引入cxf3需要在pom.xml加入如下内容: <dependency> <groupId>org.apache.c ...