回顾

  上一篇我们根据工作单元的原理基于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. SQL——字符串处理函数

    1) ASCII Format:ASCII ( character_expression ) Function:返回表达式最左端字符的ASCII值. eg: select ASCII('abcdef' ...

  2. 由于外键的存在引发的一个mysql问题 Cannot change column 'id': used in a foreign key constraint

    Duplicate entry ' for key 'PRIMARY' 一查,发现表没有设置自增长. 尝试增加修改表,添加自增长. ALTER TABLE sh_incentive_item MODI ...

  3. 再谈this

    不管学习什么知识,习惯于把自己所学习的知识列成一个list,会有助于我们理清思路,是一个很好的学习方法.强烈推荐. 以下篇幅有点长,希望读者耐心阅读. 以下内容会分为如下部分: 1.涵义 1.1:th ...

  4. Atitit.如何选择技术职业方向

    Atitit.如何选择技术职业方向 1. 原则是应该如下的应该从以下指标判断1 1.1. 技术的长寿性(长生命周期1 1.2. 技术的普适性(市场份额)1 1.3. **属于open体系还是封闭体系? ...

  5. Tamper Data

    一款可以修改表单的火狐浏览器插件

  6. SQL Server 内存中OLTP内部机制概述(四)

    ----------------------------我是分割线------------------------------- 本文翻译自微软白皮书<SQL Server In-Memory ...

  7. sqlserver内存释放心得

    SQL Server 2008 或者R2的默认内存分配是2147483647MB, 差不多算是无穷大,对于系统内存的管理策略是有多少占多少.SQLserver会把所有处理过的SQL操作缓存在内存里,这 ...

  8. Javascript中的Prototype到底是啥

    Javascript也是面向对象的语言,但它是一种基于原型Prototype的语言,而不是基于类的语言.在Javascript中,类和对象看起来没有太多的区别. 通常,这样创建一个对象: functi ...

  9. 用 Mahout 和 Elasticsearch 实现推荐系统

    原文地址 本文内容 软件 步骤 控制相关性 总结 参考资料 本文介绍如何用带 Apache Mahout 的 MapR Sandbox for Hadoop 和 Elasticsearch 搭建推荐引 ...

  10. TNSNAMES.ORA 配置

    上面的sqlnet.ora文件说明:SQLNET.AUTHENTICATION_SERVICES= (NTS)——这个表示采用os认证,在数据库服务器上,可以利用sqlplus “/ as sysdb ...