UnitOfWork机制的实现和注意事项
UnitOfWork机制
/*一点牢骚:
* UnitOfWork机制的蛋疼之处:
* UnitOfWork机制,决定了插入新的实体前,要预先设置数据库中的主键Id,尽管数据库自己生产主键。
* 但是,如果自己能生成主键还要数据库自动生成主键干什么,即使自己生成主键不能保证主键的唯一性,
* 除非主键是GUID。
*
* if (!addedEntities.ContainsKey(entity))
{
addedEntities.Add(entity, unitofWorkRepository);
};
* 判断实体的唯一性标准是调用实体的GetHashCode();
* public override int GetHashCode()
{
return this.Id.GetHashCode();
}
*而 this.Id是实体在数据库的主键(一般用数据库自动生成),但我插入前怎么能由我生成能。
*如果人工生成不能保证主键的唯一性,就不能添加到所以addedEntities中,也就不能保存到数据库。
*折中的解决方案是每添加一个新的实体,就Commit一次(马上提交到数据库,并清空addedEntities)。
*
*/
---------------------------------------------------------冷静分割线---------------------------------------------------
仓储实现UintOfWork机制
1.目标:
实现仓储实现UintOfWork机制(UintOfWork机制的目的是实现实体的持久化操作的原子性,保证数据的一致性)
2.具体的实现思路:
图解:

伪代码:
(1)仓储类Repository的定义
Repository类
{
虚拟增(实体entity) {
UintOfWork对象.增登记(实体entity,this) }; 虚拟删(实体entity) {
UintOfWork对象.删登记(实体entity,this) }; 虚拟改Add(实体entity) {
UintOfWork对象. 改登记(实体entity,this) }; 真的增到数据库(实体entity) {
AddTo数据库(实体entity)
}; 真的删到数据库(实体entity) {
RemovFrom数据库(实体entity)
}; 真的改保存到数据库(实体entity) {
UpdateTo数据库(实体entity)
};
}
(2)UnitOfWork类的定义:
UnitOfWork
{ 被增实体的字典 = new ();
被删实体的字典 = new ();
被改实体的字典 = new(); 增登记(实体entity,Repository)
{
if(如果被增实体的字典包不含实体entity)
被增实体的字典.Add(实体entity,Repository);
} 删登记(实体entity,Repository)
{
if (如果被删实体的字典不包含实体enity)
被删实体的字典.Add(实体entity,Repository);
} 改登记(实体entity,Repository)
{ if(如果被改实体的字典不包含实体entity)
被改实体的字典.Add(实体entity,Repository);
} 统一提交到数据库Commit()
{
for(int i = ; i < 被增实体的字典.lengh; ++i )
{
实体entity tmpEntity = 被增实体的字典[i].Key;
Repository repository = 被增实体的字典[i].Value;
repository.真的增保存到数据库(tmpEntity);
} for(int i = ; i < 被删实体的字典.lengh; ++i )
{
实体entity tmpEntity = 被删实体的字典[i].Key;
Repository repository = 被删实体的字典[i].Value;
repository.真的删保存到数据库(tmpEntity);
} for(int i = ; i < 被改实体的字典.lengh; ++i )
{
实体entity tmpEntity = 被改实体的字典[i].Key;
Repository repository = 被改实体的字典[i].Value;
repository.真的改保存到数据库(tmpEntity);
}
}
}
3.光说不练,代码实现:
IUnitOfWorkRepository.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NCS.Infrastructure.Domain; namespace NCS.Infrastructure.UnitOfWork
{
/// <summary>
/// Repository实现了UnitOfWork机制的Repository
/// </summary>
public interface IUnitOfWorkRepository
{
/// <summary>
/// 实体的持久化操作(包括三个操作:增Add、删remove、改save,注意不包括查询)前,
/// 先用UnitOfWork进行登记,
/// 以便日后由UnitOfWork统一(原子性)通过Commit操作,提交修改到数据库(持久化操作)
/// </summary>
IUnitOfWork UnitOfWork { get; set; } /**
* Persist持久化系列函数
*/
void PersistCreationOf(IAggregateRoot entity);
void PersistUpdateOf(IAggregateRoot entity);
void PersistDeletionOf(IAggregateRoot entity);
}
}
IUnitOfWork.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NCS.Infrastructure.Domain; namespace NCS.Infrastructure.UnitOfWork
{
/// <summary>
/// UnitOfWork模式:
/// 1.跟踪领域实体聚合的变化
/// 2.原子操作中完成实体聚合的持久化
/// 3.具体实现:
/// 实体的进行持久化操作(包括三个操作:增Add、删remove、改save,注意不包括查询)前,
/// 先用UnitOfWork进行登记,
/// 以便日后由UnitOfWork统一(原子性)通过Commit操作,提交修改到数据库(持久化操作)
/// </summary>
/// </summary>
public interface IUnitOfWork
{
/// <summary>
/// 注册登记被添加的实体
/// </summary>
/// <param name="entity">目标实体</param>
/// <param name="unitofWorkRepository">实体所在的仓储</param>
void RegisterNew(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository);
/// <summary>
/// 注册登记被删除的实体
/// </summary>
/// <param name="entity">目标实体</param>
/// <param name="unitofWorkRepository">实体所在的仓储</param>
void RegisterRemoved(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository);
/// <summary>
/// 注册登记被修改的实体
/// </summary>
/// <param name="entity">目标实体</param>
/// <param name="unitofWorkRepository">实体所在的仓储</param>
void RegisterAmended(IAggregateRoot entity, IUnitOfWorkRepository unitofWorkRepository); void Commit();
}
}
AdoUnitOfWork.cs
/*一点牢骚:
* UnitOfWork机制的蛋疼之处:
* UnitOfWork机制,决定了插入新的实体前,要预先设置数据库中的主键Id,尽管数据库自己生产主键。
* 但是,如果自己能生成主键还要数据库自动生成主键干什么,即使自己生成主键不能保证主键的唯一性,
* 除非主键是GUID。
*
* if (!addedEntities.ContainsKey(entity))
{
addedEntities.Add(entity, unitofWorkRepository);
};
* 判断实体的唯一性标准是调用实体的GetHashCode();
* public override int GetHashCode()
{
return this.Id.GetHashCode();
}
*而 this.Id是实体在数据库的主键(一般用数据库自动生成),但我插入前怎么能由我生成呢!!!
*因为:
*1.不知主键的数据库类型;
*2.即使知道主键的数据库类型,也不能因为硬编码造成的依赖,耦合。
*3.人工生成不能保证主键的唯一性,
*综上,所以就不能添加到addedEntities中,也就不能保存到数据库。
*折中的解决方案是每添加一个新的实体,就Commit一次(马上提交到数据库,并清空addedEntities)。
*
*/ using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NCS.Infrastructure.Domain;
using NCS.Infrastructure.UnitOfWork;
using System.Transactions; namespace NCS.Repository.ADO
{
public class AdoUnitOfWork : IUnitOfWork
{
private Dictionary<IAggregateRoot, IUnitOfWorkRepository> addedEntities;
private Dictionary<IAggregateRoot, IUnitOfWorkRepository> changedEntities;
private Dictionary<IAggregateRoot, IUnitOfWorkRepository> deletedEntities; public AdoUnitOfWork()
{
addedEntities = new Dictionary<IAggregateRoot, IUnitOfWorkRepository>();
changedEntities = new Dictionary<IAggregateRoot, IUnitOfWorkRepository>();
deletedEntities = new Dictionary<IAggregateRoot, IUnitOfWorkRepository>();
} #region IUnitOfWork member #region 注册登记实体
public void RegisterNew(IAggregateRoot entity,
IUnitOfWorkRepository unitofWorkRepository)
{
if (!addedEntities.ContainsKey(entity))
{
addedEntities.Add(entity, unitofWorkRepository);
};
} public void RegisterRemoved(IAggregateRoot entity,
IUnitOfWorkRepository unitofWorkRepository)
{
if (!deletedEntities.ContainsKey(entity))
{
deletedEntities.Add(entity, unitofWorkRepository);
}
} public void RegisterAmended(IAggregateRoot entity,
IUnitOfWorkRepository unitofWorkRepository)
{
if (!changedEntities.ContainsKey(entity))
{
changedEntities.Add(entity, unitofWorkRepository);
}
} #endregion
public void Commit()
{
using (TransactionScope scope = new TransactionScope())
{
foreach (IAggregateRoot entity in this.addedEntities.Keys)
{
this.addedEntities[entity].PersistCreationOf(entity);
} foreach (IAggregateRoot entity in this.changedEntities.Keys)
{
this.changedEntities[entity].PersistUpdateOf(entity);
} foreach (IAggregateRoot entity in this.deletedEntities.Keys)
{
this.deletedEntities[entity].PersistDeletionOf(entity);
} scope.Complete(); this.addedEntities.Clear();
this.changedEntities.Clear();
this.deletedEntities.Clear();
}
} #endregion }
}
Repository.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NCS.Infrastructure.Domain;
using NCS.Infrastructure.Querying;
using NCS.Infrastructure.UnitOfWork;
using NCS.Repository.ADO.DataSession; namespace NCS.Repository.ADO.Repositories
{
public abstract class Repository<T, TEntityKey> : IUnitOfWorkRepository
where T : IAggregateRoot
{
private IUnitOfWork unitOfWork; private IDataSession<T, TEntityKey> dataSession; public Repository(IUnitOfWork unitOfWork)
{
this.UnitOfWork = unitOfWork;
DataSession = DataSessionFactory.GetDataSession<T, TEntityKey>();
} public IUnitOfWork UnitOfWork
{
get { return unitOfWork; }
set { unitOfWork = value; }
} public IDataSession<T, TEntityKey> DataSession
{
get { return dataSession; }
set { dataSession = value; }
} #region 持久化 public void Add(T entity)
{
UnitOfWork.RegisterNew(entity, this);
} public void Remove(T entity)
{
UnitOfWork.RegisterNew(entity, this);
} public void Remove(Query query)
{
//TODO:好像Remove(Query query)并不能保证事务操作,因为没添加到UnitOfWork里面
//先提交事务
unitOfWork.Commit(); DataSession = DataSessionFactory.GetDataSession<T, TEntityKey>();
DataSession.Remove(query); } public void Save(T entity)
{
UnitOfWork.RegisterRemoved(entity, this);
} #endregion #region 查询部分 public T FindBy(TEntityKey id)
{
return this.DataSession.FindBy(id);
} public IEnumerable<T> FindAll()
{
return this.DataSession.FindAll();
} public IEnumerable<T> FindAll(int index, int count)
{
return this.DataSession.FindAll().Skip(index).Take(count);
} public IEnumerable<T> FindBy(Query query)
{
return this.DataSession.FindBy(query);
} public IEnumerable<T> FindBy(Query query, int index, int count)
{
return this.DataSession.FindBy(query, index, count);
} #endregion #region IUnitOfWorkRepository members public virtual void PersistCreationOf(IAggregateRoot entity)
{
this.DataSession.Add((T)entity);
} public virtual void PersistUpdateOf(IAggregateRoot entity)
{
this.DataSession.Save((T)entity);
} public virtual void PersistDeletionOf(IAggregateRoot entity)
{
this.DataSession.Remove((T)entity);
} #endregion }
}
UnitOfWork机制的实现和注意事项的更多相关文章
- docker build 的 cache 机制
cache 机制注意事项 可以说,cache 机制很大程度上做到了镜像的复用,降低存储空间的同时,还大大缩短了构建时间.然而,不得不说的是,想要用好 cache 机制,那就必须了解利用 cache 机 ...
- Node基础篇(模块和NPM)
核心模块 核心模块的意义 如果只是在服务器运行JavaScript代码,意义并不大,因为无法实现任何功能(读写文件,访问网络). Node 的用处在于它本身还提供的一系列功能模块,用于与操作系统互动. ...
- node学习笔记
一.准备(github地址) 什么是Javascript? ... Javascript能做什么? ..... 浏览器中的Javascript可以做什么? 操作DOM(增删改查) AJAX/跨域 BO ...
- 【Bugly干货】Android性能优化典范之多线程篇
本文涉及的内容有:多线程并发的性能问题,介绍了 AsyncTask,HandlerThread,IntentService 与 ThreadPool 分别适合的使用场景以及各自的使用注意事项,这是一篇 ...
- Android性能优化典范 - 第5季
这是Android性能优化典范第5季的课程学习笔记,拖拖拉拉很久,记录分享给大家,请多多包涵担待指正!文章共10个段落,涉及的内容有:多线程并发的性能问题,介绍了AsyncTask,HandlerTh ...
- Python_socket常见的方法、网络编程的安全注意事项、socketsever模块、浏览器中在一段时间记录用户的登录验证机制
1.socket常见的方法 socket_常见方法_服务器端 import socket from socket import SOL_SOCKET,SO_REUSEADDR sk = socket. ...
- Golang Vendor 包机制 及 注意事项
现在的 Go 版本是 1.8,早在 1.5 时期,就有了 Vendor 包机制,详情可查看博文:“理解 Go 1.5 vendor”. 遇到的问题 个人在使用 Glide 管理 Vendor 包时(附 ...
- Android消息机制使用注意事项,防止泄漏
在Android的线程通信当中,使用频率最多的就是Android的消息处理机制(Handler.send().View.post().Asynctask.excute()等等都使用到了消息处理机制). ...
- Android:onNewIntent()触发机制及注意事项
一.onNewIntent() 在IntentActivity中重写下列方法:onCreate onStart onRestart onResume onPause onStop onDestro ...
随机推荐
- SQLite CRUD操作
SQLite CRUD操作代码实例: 1:首先创建一个继承了SQLiteOpenHelper类的MyDatabaseHelper类.实现他的onCreate(SQLiteDatabase db) on ...
- 函数 datediff(根据objid 获取同name 同年度最近的4条记录)
显示 包括选择的这条,在加上 选择年度的此人 最近的 3条.(最多显示4条) . 记录数大于4条 . 全显示 create table temp( objid ,) primary key , nam ...
- jquery之音乐均衡器
制作这个音乐均衡器需要一个equalizer插件(插件我已经上传),下面介绍一下网页的BGM的相关属性: hidden="true"表示隐藏播放,即不显示播放器的外观,若要想显示, ...
- 承接VR/AR内容应用定制需求
业务范围: 1 承接VR/AR内容应用定制需求: 教育培训.建筑建设.旅游体验.课件教学系统.交通车辆仿真,模拟驾驶系统.游戏等.2 各类最新VR设备,例如GearVR.HTC vive.Oculus ...
- Swift项目开发实战-基于分层架构的多版本iPhone计算器-直播公开课
Swift项目开发实战-基于分层架构的多版本iPhone计算器-直播公开课 本课程采用Q Q群直播方式进行直播,价值99元视频课程免费直播.完整的基于Swift项目实战,手把手教你做一个Swift版i ...
- PHP学习笔记 - 进阶篇(9)
PHP学习笔记 - 进阶篇(9) 图形图像操作 GD库简介 GD指的是Graphic Device,PHP的GD库是用来处理图形的扩展库,通过GD库提供的一系列API,可以对图像进行处理或者直接生成新 ...
- npm install --save 与 npm install --save-dev 的区别
以npm安装msbuild为例: npm install msbuild: 会把msbuild包安装到node_modules目录中 不会修改package.json 之后运行npm install命 ...
- Javascript中数组
Javascript中数组 1.什么是数组 所谓的数组就是一组数据的集合,在内存中表现为一段连续的内存地址(保存在堆内存) 2.创建数组的含义 创建数组的目的:就是为了保存更多的数据 3.数组的定义 ...
- Apache 使用密码文件验证用户
使用文本文件作为密码文件 创建密码文件 需要使用htpasswd.exe文件来创建用户密码文件 语法: htpasswd -c '文件完整路径' 用户名 向一个用户密码文件中添加一个新用户 语法: h ...
- QT编译mysql驱动
一. 下载mysql C链接库 地址:http://dev.mysql.com/downloads/ 根据当前系统选择下载: 二. 安装下载好的mysql驱动文件 注意,一定要安装在不含有中文.空格以 ...