工作单元模式(UnitOfWork)学习总结
工作单元的目标是维护变化的对象列表。使用IUnitOfWorkRepository负责对象的持久化,使用IUnitOfWork收集变化的对象,并将变化的对象放到各自的增删改列表中,
最后Commit,Commit时需要循环遍历这些列表,并由Repository来持久化。
要实现一个银行卡简单转账的功能,Demo框架如下设计:

代码实现如下:
EntityBase,领域类的基类。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Jack.Gao.UnitOfWork.Infrastructure
{
public class EntityBase
{ }
}
IUnitOfWork,复杂维护变化的对象列表,并最后Commit,依次遍历变化的列表,并持久化,这就是Commit的事情。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Jack.Gao.UnitOfWork.Infrastructure
{
public interface IUnitOfWork
{
void RegisterAdded(EntityBase entityBase, IUnitOfWorkRepository unitOfWorkRepository);
void RegisterChangeded(EntityBase entityBase, IUnitOfWorkRepository unitOfWorkRepository);
void RegisterRemoved(EntityBase entityBase, IUnitOfWorkRepository unitOfWorkRepository);
void Commit();
}
}
IUnitOfWorkRepository,负责持久化对象。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Jack.Gao.UnitOfWork.Infrastructure
{
public interface IUnitOfWorkRepository
{
void PersistNewItem(EntityBase entityBase);
void PersistUpdatedItem(EntityBase entityBase);
void PersistDeletedItem(EntityBase entityBase);
}
}
UnitOfWork,IUnitOfWork的具体实现。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions; namespace Jack.Gao.UnitOfWork.Infrastructure
{
public class UnitOfWork:IUnitOfWork
{
#region Fields private Dictionary<EntityBase, IUnitOfWorkRepository> addedEntities;
private Dictionary<EntityBase, IUnitOfWorkRepository> changededEntities;
private Dictionary<EntityBase, IUnitOfWorkRepository> removedEntities; #endregion #region Constructor public UnitOfWork()
{
addedEntities=new Dictionary<EntityBase, IUnitOfWorkRepository>();
changededEntities=new Dictionary<EntityBase, IUnitOfWorkRepository>();
removedEntities=new Dictionary<EntityBase, IUnitOfWorkRepository>();
} #endregion #region Implement IUnitOfWork public void RegisterAdded(EntityBase entityBase, IUnitOfWorkRepository unitOfWorkRepository)
{
this.addedEntities.Add(entityBase,unitOfWorkRepository);
} public void RegisterChangeded(EntityBase entityBase, IUnitOfWorkRepository unitOfWorkRepository)
{
this.changededEntities.Add(entityBase,unitOfWorkRepository);
} public void RegisterRemoved(EntityBase entityBase, IUnitOfWorkRepository unitOfWorkRepository)
{
this.removedEntities.Add(entityBase,unitOfWorkRepository);
} public void Commit()
{
using (TransactionScope transactionScope=new TransactionScope())
{
foreach (var entity in addedEntities.Keys)
{
addedEntities[entity].PersistNewItem(entity);
} foreach (var entity in changededEntities.Keys)
{
changededEntities[entity].PersistUpdatedItem(entity);
} foreach (var entity in removedEntities.Keys)
{
removedEntities[entity].PersistDeletedItem(entity);
} transactionScope.Complete();
}
} #endregion
}
}
BankAccount,继承自领域基类EntityBase。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; using Jack.Gao.UnitOfWork.Infrastructure; namespace Jack.gao.UnitOfWork.Domain
{
public class BankAccount:EntityBase
{
#region Field public int Id { get; set; } public decimal Balance { get; set; } #endregion #region operator + public static BankAccount operator+(BankAccount accountLeft,BankAccount accountRight)
{
BankAccount account = new BankAccount(); account.Balance = accountLeft.Balance + accountRight.Balance; return account;
} #endregion
}
}
IAccountRepository,持久化BankAcount接口
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace Jack.gao.UnitOfWork.Domain
{
public interface IAccountRepository
{
void Save(BankAccount account);
void Add(BankAccount account);
void Remove(BankAccount account);
}
}
BankAccountService,服务类,实现转账服务。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Jack.Gao.UnitOfWork.Infrastructure; namespace Jack.gao.UnitOfWork.Domain
{
public class BankAccountService
{
#region Field private IAccountRepository _accountRepository;
private IUnitOfWork _unitOfWork; #endregion #region Constructor public BankAccountService(IAccountRepository accountRepository, IUnitOfWork unitOfWork)
{
this._accountRepository = accountRepository;
this._unitOfWork = unitOfWork;
} #endregion #region Method public void TransferMoney(BankAccount from, BankAccount to, decimal balance)
{
if (from.Balance>=balance)
{
from.Balance = from.Balance - balance;
to.Balance = to.Balance + balance; _accountRepository.Save(from);
_accountRepository.Save(to);
_unitOfWork.Commit();
}
} #endregion
}
}
AccountRepository,持久化具体实现,使用ADO.NET实现,也可以使用其他的EF,NHbernate
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Jack.gao.UnitOfWork.Domain;
using Jack.Gao.UnitOfWork.Infrastructure;
using System.Data.SqlClient; namespace Jack.gao.UnitOfWork.Persistence
{
public class AccountRepository:IAccountRepository,IUnitOfWorkRepository
{
#region Field private const string _connectionString = @"Data Source=T57649\MSSQLSERVER2012;Initial Catalog=DB_Customer;Integrated Security=True"; private IUnitOfWork _unitOfWork; #endregion #region Constructor public AccountRepository(IUnitOfWork unitOfWork)
{
this._unitOfWork = unitOfWork;
} #endregion #region Implement interface IAccountRepository,IUnitOfWorkRepository public void Save(BankAccount account)
{
_unitOfWork.RegisterChangeded(account,this);
} public void Add(BankAccount account)
{
_unitOfWork.RegisterAdded(account,this);
} public void Remove(BankAccount account)
{
_unitOfWork.RegisterRemoved(account,this);
} public void PersistNewItem(EntityBase entityBase)
{
BankAccount account = (BankAccount)entityBase; string insertAccountSql = string.Format("insert into DT_Account(balance,Id) values({0},{1})", account.Balance, account.Id); SqlConnection sqlConnection = new SqlConnection(_connectionString); try
{
sqlConnection.Open(); SqlCommand sqlCommand = new SqlCommand(insertAccountSql, sqlConnection); sqlCommand.ExecuteNonQuery();
}
catch (Exception ex)
{
throw ex;
}
finally
{
sqlConnection.Close();
}
} public void PersistUpdatedItem(EntityBase entityBase)
{
BankAccount account = (BankAccount)entityBase; string updateAccountSql = string.Format("update DT_Account set balance={0} where Id={1}", account.Balance,account.Id); SqlConnection sqlConnection = new SqlConnection(_connectionString); try
{
sqlConnection.Open(); SqlCommand sqlCommand = new SqlCommand(updateAccountSql, sqlConnection); sqlCommand.ExecuteNonQuery();
}
catch (Exception ex)
{
throw ex;
}
finally
{
sqlConnection.Close();
}
} public void PersistDeletedItem(EntityBase entityBase)
{
BankAccount account = (BankAccount)entityBase; string deleteAccountSql = string.Format("delete from DT_Account where Id={0}", account.Id); SqlConnection sqlConnection = new SqlConnection(_connectionString); try
{
sqlConnection.Open(); SqlCommand sqlCommand = new SqlCommand(deleteAccountSql, sqlConnection); sqlCommand.ExecuteNonQuery();
}
catch (Exception ex)
{
throw ex;
}
finally
{
sqlConnection.Close();
}
} #endregion #region Method public BankAccount GetAccount(BankAccount account)
{
account.Balance = ;
return account;
} #endregion
}
}
AccountRepositoryTest,测试AccountRepository中的方法
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Jack.gao.UnitOfWork.Domain;
using Jack.Gao.UnitOfWork.Infrastructure;
using Jack.gao.UnitOfWork.Persistence; namespace Jack.gao.UnitOfWork.Test
{
[TestClass]
public class AccountRepositoryTest
{
private IUnitOfWork unitOfWork;
private IAccountRepository accountRepository;
private BankAccountService accountService; public AccountRepositoryTest()
{
unitOfWork = new Jack.Gao.UnitOfWork.Infrastructure.UnitOfWork();
accountRepository = new AccountRepository(unitOfWork);
accountService = new BankAccountService(accountRepository, unitOfWork);
} [TestMethod]
public void Add()
{
var accountLeft = new BankAccount() { Balance = , Id = };
var accountRight = new BankAccount() { Balance = , Id = }; accountRepository.Add(accountLeft);
accountRepository.Add(accountRight); unitOfWork.Commit();
} [TestMethod]
public void Save()
{
var accountLeft = new BankAccount() { Balance = , Id = };
var accountRight = new BankAccount() { Balance = , Id = }; accountService.TransferMoney(accountLeft, accountRight, );
} [TestMethod]
public void Remove()
{
var accountLeft = new BankAccount() { Balance = , Id = }; accountRepository.Remove(accountLeft); unitOfWork.Commit();
}
}
}
工作单元模式(UnitOfWork)学习总结的更多相关文章
- 仓储(Repository)和工作单元模式(UnitOfWork)
仓储和工作单元模式 仓储模式 为什么要用仓储模式 通常不建议在业务逻辑层直接访问数据库.因为这样可能会导致如下结果: 重复的代码 编程错误的可能性更高 业务数据的弱类型 更难集中处理数据,比如缓存 无 ...
- MVC+EF 理解和实现仓储模式和工作单元模式
MVC+EF 理解和实现仓储模式和工作单元模式 原文:Understanding Repository and Unit of Work Pattern and Implementing Generi ...
- Contoso 大学 - 9 - 实现仓储和工作单元模式
原文 Contoso 大学 - 9 - 实现仓储和工作单元模式 By Tom Dykstra, Tom Dykstra is a Senior Programming Writer on Micros ...
- 演练5-8:Contoso大学校园管理系统(实现存储池和工作单元模式)
在上一次的教程中,你已经使用继承来消除在 Student 和 Instructor 实体之间的重复代码.在这个教程中,你将要看到使用存储池和工作单元模式进行增.删.改.查的一些方法.像前面的教程一样, ...
- .NET应用架构设计—工作单元模式(摆脱过程式代码的重要思想,代替DDD实现轻量级业务)
阅读目录: 1.背景介绍 2.过程式代码的真正困境 3.工作单元模式的简单示例 4.总结 1.背景介绍 一直都在谈论面向对象开发,但是开发企业应用系统时,使用面向对象开发最大的问题就是在于,多个对象之 ...
- [.NET领域驱动设计实战系列]专题四:前期准备之工作单元模式(Unit Of Work)
一.前言 在前一专题中介绍了规约模式的实现,然后在仓储实现中,经常会涉及工作单元模式的实现.然而,在我的网上书店案例中也将引入工作单元模式,所以本专题将详细介绍下该模式,为后面案例的实现做一个铺垫. ...
- 关于工作单元模式——工作单元模式与EF结合的使用
工作单元模式往往和仓储模式一起使用,本篇文章讲到的是工作单元模式和仓储模式一起用来在ef外面包一层,其实EF本身就是工作单元模式和仓储模式使用的经典例子,其中DbContext就是工作单元,而每个Db ...
- [.NET领域驱动设计实战系列]专题五:网上书店规约模式、工作单元模式的引入以及购物车的实现
一.前言 在前面2篇博文中,我分别介绍了规约模式和工作单元模式,有了前面2篇博文的铺垫之后,下面就具体看看如何把这两种模式引入到之前的网上书店案例里. 二.规约模式的引入 在第三专题我们已经详细介绍了 ...
- 重新整理 .net core 实践篇—————工作单元模式[二十六]
前言 简单整理一下工作单元模式. 正文 工作单元模式有3个特性,也算是其功能: 使用同一上下文 跟踪实体的状态 保障事务一致性 工作单元模式 主要关注事务,所以重点在事务上. 在共享层的基础建设类库中 ...
随机推荐
- 第59讲:Scala中隐式转换初体验
今天学习了下隐式转换的内容.所谓隐式转换,就是说,一个实例拥用1 2 3方法,但是当它需要4方法的时候,它没有,但是却可以通过转换成另一种类型来调用4方法,而且这种转换是自动转换不需要人为干预的,这种 ...
- js 经典正则判断 一个字符串是否包含另一个字符串
if (!new RegExp(list_table[i].value.split("—")[0]).test(lhtj)) { }判断在lhtj中是否包含list_table[i ...
- 归并排序-java
排序-归并排序 基本思想:是指将两个或两个以上的有序表合并成一个新的有序表. 具体步骤: (1首先将整个表看成是n个有序子表,每个子表的长度为1. (2)然后两两归并,得到n/2个长度为2的有序子表. ...
- 解决Win7下VC6.0插入ActiveX控件对话框为空的问题
在Win7环境下,编写MFC应用程序,Project菜单下Add To Project子菜单中的 Components and Controls…选项,在弹出的对话框中Gallery文件为空,也就无法 ...
- oracle常用语句总结
一.用户管理类 1.创建用户: Create user username Identified by password Default tablespace tablespacename Tempor ...
- oracle 11g RAC public/virtual/SACN/private IP we need to know
1.3.2.2 IP Address Requirements Before starting the installation, you must have at least two interfa ...
- savepoint原理
保存点 在MySQL中, 保存点SAVEPOINT属于事务控制处理部分.利用SAVEPOINT可以回滚指定部分事务,从而使事务处理更加灵活和精细.SAVEPOINT相关的SQL语句如下 SAVEPOI ...
- Linux下Crontab命令用法
第1列分钟1-59第2列小时1-23(0表示子夜)第3列日1-31第4列月1-12第5列星期0-6(0表示星期天)第6列要运行的命令 下面是crontab的格式:分 时 日 月 星期 要运行的命令 这 ...
- [Asp.net 开发系列之SignalR篇]专题二:使用SignalR实现酷炫端对端聊天功能
一.引言 在前一篇文章已经详细介绍了SignalR了,并且简单介绍它在Asp.net MVC 和WPF中的应用.在上篇博文介绍的都是群发消息的实现,然而,对于SignalR是为了实时聊天而生的,自然少 ...
- 关于MySQL的在线扩容
原文地址:http://bucketli.iteye.com/blog/1294032 主要简单总结下,mysql在线扩容和缩容一般涉及到的内容,主要包括三个方面,1.在线也就意味着需要把增量的数据重 ...