回顾

  上一篇我们根据工作单元的原理基于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. css圆环百分比

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  2. 【原】《Git教程》学习笔记

    [TOC] 1 创建版本库 1.1 初始化 初始化一个Git仓库,使用 git init 命令. 添加文件到Git仓库,分两步: 第一步,使用命令git add <file> ,注意,可反 ...

  3. 插件~使用ECharts动态在地图上标识点

    ECharts可以很方便的在网页上绘制地图,图表,并且可以提供下载图像,放大,缩小,拖动等功能,今天主要说一下它的地图类型(type:'map')是如何实现的. 首先在ECharts地图的坐标需要我们 ...

  4. crossplatform---Node.js Applications with VS Code

    Node.js is a platform for building fast and scalable server applications using JavaScript. Node.js i ...

  5. 分析Linux内核中进程的调度(时间片轮转)-《Linux内核分析》Week2作业

    1.环境的搭建: 这个可以参考孟宁老师的github:mykernel,这里不再进行赘述.主要是就是下载Linux3.9的代码,然后安装孟宁老师编写的patch,最后进行编译. 2.代码的解读 课上的 ...

  6. Python之Django【进阶篇 】

    Model 到目前为止,当我们的程序涉及到数据库相关操作时,我们一般都会这么搞: 创建数据库,设计表结构和字段 使用 MySQLdb 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层执行 ...

  7. 如何在安装程序中判断操作系统是否是64位 inno

    [Setup]; 开启64位模式ArchitecturesInstallIn64BitMode=x64 [Run] ;根据是否是64位进行不同的操作Filename: "..."; ...

  8. android recycleview 中禁止多点触发

    int currentapiVersion = android.os.Build.VERSION.SDK_INT; if (currentapiVersion >= android.os.Bui ...

  9. IIS7显示ASP的详细错误信息到浏览器

    服务端环境:Windows2008 + IIS7 客户端浏览器设置:取消“显示友好的HTTP错误信息” IIS7设置(GUI): 1. 网站->ASP->调试属性->将错误发送到浏览 ...

  10. C#:WebBrowser中伪造referer,为何对流量统计器无效?

    使用webbrowser伪造referer的方法:webBrowser1.Navigate(url, "_self", null, "Referer:http://www ...