UnitOfWork
数据访问层之UnitOfWork

本章我们继续IUnitOfWork的开发,从之前的IRepository接口中就可以看出,我们并没有处理单元事务,
数据CUD每次都是立即执行的,这样有一些不好的地方,比如数据访问次数会增多,一笔数据的完整性无法保证
比如:批量新增2条记录,只有一条成功,这样的情况就应该Rollback;可能有人已经想到用数据库自带的事务保证完整性
虽然是可以,但是这样就不可避免地在业务层耦合SqlTransaction,我不想这种情况出现;
所以我们用windows自带的分布式事务TransactionScope来实现,TransactionScope可以实现多个数据库的事务锁,这点就比SqlTransaction强一些
当然我了解到分布式事务是不一般的复杂的,那些更好的处理方式我还没有掌握,所以先这么写吧,有这方面经验的朋友欢迎提建议
IUnitOfWork.cs

1 public interface IUnitOfWork<T> where T : class
2 {
3 void RegisterAdd(T entity, Action callback);
4 void RegisterUpdate(T entity, Action callback);
5 void RegisterDelete(T entity, Action callback);
6 void Commit();
7 }

注册新增操作:RegisterAdd
注册更新操作:RegisterUpdate
注册修改操作:RegisterDelete
提交数据:Commit
工作单元的实现

1 public class UnitOfWork<T> : IUnitOfWork<T> where T : class
2 {
3 private Dictionary<T, Action> addEntities;
4 private Dictionary<T, Action> updateEntities;
5 private Dictionary<T, Action> deleteEntities;
6
7 public UnitOfWork()
8 {
9 addEntities = new Dictionary<T, Action>();
10 updateEntities = new Dictionary<T, Action>();
11 deleteEntities = new Dictionary<T, Action>();
12 }
13
14 public void RegisterAdd(T entity, Action callback)
15 {
16 this.addEntities.Add(entity, callback);
17 }
18
19 public void RegisterUpdate(T entity, Action callback)
20 {
21 this.updateEntities.Add(entity, callback);
22 }
23
24 public void RegisterDelete(T entity, Action callback)
25 {
26 this.deleteEntities.Add(entity, callback);
27 }
28
29 public void Commit()
30 {
31 using (TransactionScope scope = new TransactionScope())
32 {
33 foreach (var entity in deleteEntities.Keys)
34 {
35 this.deleteEntities[entity]();
36 }
37
38 foreach (var entity in updateEntities.Keys)
39 {
40 this.updateEntities[entity]();
41 }
42
43 foreach (var entity in addEntities.Keys)
44 {
45 this.addEntities[entity]();
46 }
47
48 scope.Complete();
49 }
50 }
51 }

这里我们用了Action,这个是无返回值委托方法,如果大家需要返回值可以用Func
实现我们还是用DapperRepository,修改一下。在新增方法中注册数据持久化方法

好了,现在我们来看看测试结果
测试工作单元

还是用原来那个DapperRepositoryTest
我们修改一下实现过程:
单个新增

批量新增

运行结果

我们把表结构改一下,名称改成不能为null

AddBatch也要修改,正常的执行结果一个是抛出异常

1 [TestMethod]
2 public void AddBatch()
3 {
4 try
5 {
6 var loginUser1 = new LoginUser()
7 {
8 Id = Guid.NewGuid(),
9 LoginName = "lanxiaoke-" + Guid.NewGuid().ToString(),
10 Password = "mima1987",
11 IsEnabled = 1,
12 CreateTime = DateTime.Now
13 };
14
15 var loginUser2 = new LoginUser()
16 {
17 Id = Guid.NewGuid(),
18 //LoginName = "lanxiaoke-" + Guid.NewGuid().ToString(),
19 Password = "mima1987",
20 IsEnabled = 1,
21 CreateTime = DateTime.Now
22 };
23
24 var list = new List<LoginUser>();
25 list.Add(loginUser1);
26 list.Add(loginUser2);
27
28 repository.AddBatch(list);
29 unitOfWork.Commit();
30 }
31 catch (Exception ex)
32 {
33 var err = ex.Message;
34 }
35
36 //long count = repository.Count(t => t.LoginName.In(new string[] { loginUser1.LoginName, loginUser2.LoginName }));
37
38 //Assert.AreEqual(true, count >0);
39 }

运行看看

如期运行,到这里,工作单元就讲完了
完整项目架构
我们来看看完整的数据访问层架构

整个数据访问层就讲完了,虽然有些简陋,但是基本功能都有了
项目架构开发系列
UnitOfWork的更多相关文章
- 【无私分享:ASP.NET CORE 项目实战(第五章)】Repository仓储 UnitofWork
目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 本章我们来创建仓储类Repository 并且引入 UnitOfWork 我对UnitOfWork的一些理解 UnitOfW ...
- UnitOfWork以及其在ABP中的应用
Unit Of Work(UoW)模式在企业应用架构中被广泛使用,它能够将Domain Model中对象状态的变化收集起来,并在适当的时候在同一数据库连接和事务处理上下文中一次性将对象的变更提交到数据 ...
- MVC+UnitOfWork+Repository+EF 之我见
UnitOfWork+Repository模式简介: 每次提交数据库都会打开一个连接,造成结果是:多个连接无法共用一个数据库级别的事务,也就无法保证数据的原子性.一致性.解决办法是:在Reposito ...
- 工作单元模式(UnitOfWork)学习总结
工作单元的目标是维护变化的对象列表.使用IUnitOfWorkRepository负责对象的持久化,使用IUnitOfWork收集变化的对象,并将变化的对象放到各自的增删改列表中, 最后Commit, ...
- 开发笔记:用不用UnitOfWork以及Repository返回什么集合类型
这2天实际开发中明确的东西,在这篇博文中记录一下. 之前对是否需要自己封装UnitOfWork有些犹豫,因为Entity Framework就是一个UnitOfWork实现, 自己再封装一下显得有些多 ...
- DDD:Repository和UnitOfWork的生命周期问题
UnitOfWork UnitOfWork是一种有状态的.用例级别的对象.如果不采用ORM是不会使用UnitOfWork模式的, Repository Repository是一种特殊的领域服务,因此是 ...
- [Architect] Abp 框架原理解析(5) UnitOfWork
本节目录 介绍 分析Abp源码 实现UOW 介绍 UOW(全称UnitOfWork)是指工作单元. 在Abp中,工作单元对于仓储和应用服务方法默认开启.并在一次请求中,共享同一个工作单元. 同时在Ab ...
- UnitOfWork机制的实现和注意事项
UnitOfWork机制 /*一点牢骚: * UnitOfWork机制的蛋疼之处: * UnitOfWork机制,决定了插入新的实体前,要预先设置数据库中的主键Id,尽管数据库自己生产主键. * ...
- Linq 与UnitOfWork
submitchages(linq to sql)或者savechanges(ef)的次数是根据你操作方法的数量决定的,也即是:它只认识自己的提交语句(submtchanges,savechanges ...
- 关于 Repository和UnitOfWork 模式的关系
本以为,关于这方面的理解,园子中的文章已经很多的了,再多做文章真的就“多做文章了”,但是最近发现,还是有必要的,首先,每个人对于同一事物的理解方式和出发点都是不同的,所以思考的方式得到结果也是不同的. ...
随机推荐
- Searching with regular sentences will only get you so far – if you need to find something a bit tricky turn to these advanced yet simple methods--转
原文地址:http://www.theguardian.com/technology/2016/jan/15/how-to-use-search-like-a-pro-10-tips-and-tric ...
- akka---Getting Started Tutorial (Java): First Chapter
原文地址:http://doc.akka.io/docs/akka/2.0.2/intro/getting-started-first-java.html Introduction Welcome t ...
- IOS基础:深入理解Objective-c中@class 和#import的区别
在面向对象objective-C语言中,当一个类使用到另一个类时,并且在类的头文件中需要创建被引用的指针时,可以#import方式引入,通过@class引入: 这两种的方式的区别在于: 1.运用#im ...
- 初识Visual Studio Code 一.使用Visual Studio Code 开发C# 控制台程序
原文:初识Visual Studio Code 一.使用Visual Studio Code 开发C# 控制台程序 1. 安装.NET Core 安装包下载地址:https://www.microso ...
- 键盘钩子监测按键后,获取键码及按键名称(MFC)
LRESULT CALLBACK LowLevelKeyboardProc(int nCode,WPARAM wParam,LPARAM lParam){ if(nCode ==HC_ACTION & ...
- js 99乘法表
哈哈哈,笑死我了,突然怀念学习时代,撸了一个乘法表 for(let a=1;a<10;a++){let str = ''; for(let b=1;b<10;b++){ str = str ...
- 【record】9.24..10.1
因为参加比赛所以做得比较少了
- ios开发缓存处理类NSCash类的了解与使用
一:NSCash的基本了解 #import "ViewController.h" @interface ViewController ()<NSCacheDelegate&g ...
- css样式继承规则详解
css样式继承规则详解 一.总结 一句话总结:继承而发生样式冲突时,最近祖先获胜(最近原则). 1.继承中哪些样式不会被继承? 多数边框类属性,比如象Padding(补白),Margin(边界),背景 ...
- 【社交分享SDK】ShareSDK for Android 2.5.9已经公布
ShareSDK for Android 2.5.9已经公布 版本号:V2.5.9 2015-3-19 1.升级Dropbox对API接口的调用.包含授权.获取用户信息,分享三个接口 2.升级Kak ...