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 模式的关系
本以为,关于这方面的理解,园子中的文章已经很多的了,再多做文章真的就“多做文章了”,但是最近发现,还是有必要的,首先,每个人对于同一事物的理解方式和出发点都是不同的,所以思考的方式得到结果也是不同的. ...
随机推荐
- 【2017 ACM/ICPC 乌鲁木齐赛区网络赛环境测试赛 E】蒜头君的排序
[链接]h在这里写链接 [题意] 在这里写题意 [题解] 莫队算法+树状数组. 区间增加1或减少1. 对逆序对的影响是固定的. (用冒泡排序变成升序的交换次数,就是逆序对的个数) [错的次数] 0 [ ...
- GCC 编译 --sysroot
-sysroot 的作用 如果在编译时指定了-sysroot就是为编译时指定了逻辑目录.编译过程中需要引用的库,头文件,如果要到/usr/include目录下去找的情况下,则会在前面加上逻辑目录. 如 ...
- Oracle 带回滚的存储过程
create or replace procedure PROC_insertUserAmount ( userid number, msgtype number, amountvalue numbe ...
- Android java.lang.IllegalArgumentException: Object returned from onCreateLoader must not be a non-static inn
AsyncTaskLoader: http://developer.Android.com/intl/zh-CN/reference/android/content/AsyncTaskLoader.h ...
- Qt浅谈之一:内存泄露(总结),对于QWidget可以setAttribute(Qt::WA_DeleteOnClose),而且绝对不能手动删除栈上的对象
一.简介 Qt内存管理机制:Qt 在内部能够维护对象的层次结构.对于可视元素,这种层次结构就是子组件与父组件的关系:对于非可视元素,则是一个对象与另一个对象的从属关系.在 Qt 中,在 Qt 中,删除 ...
- 22、在Ubuntu 14.0上使用韦东山IP2977测试总结(未成功)
1. 去www.kernel.org下载同版本的内核(与Ubuntu 14.0) 解压后把drivers/media/video/uvc目录取出(发现我的3.13版本的在drivers\media\u ...
- js中json法创建对象(json里面的:相当于js里面的=)
js中json法创建对象(json里面的:相当于js里面的=) 一.总结 json里面的:相当于js里面的= 4.json创建js对象解决命名冲突:多个人为同一个页面写js的话,命名冲突就有可能发生, ...
- php实现用短路求值原理求1+2+3+...+n(短路求值是什么)(仔细分析题干)
php实现用短路求值原理求1+2+3+...+n(短路求值是什么)(仔细分析题干) 一.总结 1.仔细分析题干,找出要点:该递归还是得递归啊 2.短路求值原理:&&就是逻辑与,逻辑与有 ...
- 嵌入式linux串口编程(二)
/*com_writer.c*/#include "uart_api.h" int main(void){ int fd; char buff[BUFFER_SIZE]; if(( ...
- 怎样把ul li 前面的点去掉
在li 属性框里 放入 <li style="list-style-type:none;">...<li> 就可以了