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机制的实现和注意事项的更多相关文章

  1. docker build 的 cache 机制

    cache 机制注意事项 可以说,cache 机制很大程度上做到了镜像的复用,降低存储空间的同时,还大大缩短了构建时间.然而,不得不说的是,想要用好 cache 机制,那就必须了解利用 cache 机 ...

  2. Node基础篇(模块和NPM)

    核心模块 核心模块的意义 如果只是在服务器运行JavaScript代码,意义并不大,因为无法实现任何功能(读写文件,访问网络). Node 的用处在于它本身还提供的一系列功能模块,用于与操作系统互动. ...

  3. node学习笔记

    一.准备(github地址) 什么是Javascript? ... Javascript能做什么? ..... 浏览器中的Javascript可以做什么? 操作DOM(增删改查) AJAX/跨域 BO ...

  4. 【Bugly干货】Android性能优化典范之多线程篇

    本文涉及的内容有:多线程并发的性能问题,介绍了 AsyncTask,HandlerThread,IntentService 与 ThreadPool 分别适合的使用场景以及各自的使用注意事项,这是一篇 ...

  5. Android性能优化典范 - 第5季

    这是Android性能优化典范第5季的课程学习笔记,拖拖拉拉很久,记录分享给大家,请多多包涵担待指正!文章共10个段落,涉及的内容有:多线程并发的性能问题,介绍了AsyncTask,HandlerTh ...

  6. Python_socket常见的方法、网络编程的安全注意事项、socketsever模块、浏览器中在一段时间记录用户的登录验证机制

    1.socket常见的方法 socket_常见方法_服务器端 import socket from socket import SOL_SOCKET,SO_REUSEADDR sk = socket. ...

  7. Golang Vendor 包机制 及 注意事项

    现在的 Go 版本是 1.8,早在 1.5 时期,就有了 Vendor 包机制,详情可查看博文:“理解 Go 1.5 vendor”. 遇到的问题 个人在使用 Glide 管理 Vendor 包时(附 ...

  8. Android消息机制使用注意事项,防止泄漏

    在Android的线程通信当中,使用频率最多的就是Android的消息处理机制(Handler.send().View.post().Asynctask.excute()等等都使用到了消息处理机制). ...

  9. Android:onNewIntent()触发机制及注意事项

    一.onNewIntent() 在IntentActivity中重写下列方法:onCreate onStart onRestart  onResume  onPause onStop onDestro ...

随机推荐

  1. Unity3d-UI插件EZGUI官方视频教程

    Showcase Teaser (D/L) – Showcases some of the things that can be accomplished using EZ GUI.#1 – Butt ...

  2. ifndef/define/endif作用和用法

    问题:ifndef/define/endif”主要目的是防止头文件的重复包含和编译,偶只知道这个概念不懂的是怎么个用法,和为什么要用它~~高手请指点一下~~谢谢~~~!!! ------------- ...

  3. 2013年7月28日web前端学习笔记-------head相关标签应用

    7月份快过完了.趁周日写写学过觉得有用的东西. 1.缩略图的展示问题,不要以为缩略图设置了width,height,就是缩略图了.比如一个300kb的500*500原始图片,用户请求web服务器后,展 ...

  4. 北大ACM(POJ1001-Exponentiation)

    Question:http://poj.org/problem?id=1001问题点:大数运算(求幂) #include <iostream> using namespace std; # ...

  5. 结构体的malloc与数组空间

    结构体的malloc 如果结构体中有指针,对结构体的malloc 和其指针成员变量的malloc是没有关系的 结构体malloc的是存储自己地址的 忘记了面试常考试的sizeof的几个主要点 ==== ...

  6. FKCL-OS——自主的操作系统

    我想搞一个操作系统,这是因为我对windows非常不满意,对linux非常讨厌,我想要开发一个真正自己的OS,然后让自己和别人使用它.得到方便.我将在这篇文章中写下我对操作系统的不满,然后构思出我的操 ...

  7. event事件:

    onabort: 图像的加载被中断onblur: 元素失去焦点onchange: 域的内容被改变onclick: 当用户点击某个对象时调用的事件句柄ondblclick: 当用户双击某个对象时调用的事 ...

  8. [Oracle]Oracle数据库任何用户密码都能以sysdba角色登入

    * 本文相关环境:Windows 10,64位操作系统:Oracle 11gR2:toad for Oracle12.1 最近在学习Oracle数据库,使用Toad for Oracle来查看数据库的 ...

  9. MSP430F4152串口操作

    /**********************************************************************/  /*  名称:串口通讯 功能:将接到的数据组后原封不 ...

  10. python装饰器总结

    一.装饰器是什么 python的装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象.简单的说装饰器就是一个用来返回函数的函数 ...