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 模式的关系
本以为,关于这方面的理解,园子中的文章已经很多的了,再多做文章真的就“多做文章了”,但是最近发现,还是有必要的,首先,每个人对于同一事物的理解方式和出发点都是不同的,所以思考的方式得到结果也是不同的. ...
随机推荐
- Leetcode之Best Time to Buy and Sell Stock
Say you have an array for which the ith element is the price of a given stock on day i. If you were ...
- Oracle数据库(二)
指令来练习 1.password,修改密码输入旧命令,在输入新的命令 2.查询当前用户 show user: 2.查询用户下的所有对象,使用tab表,tab是每一个用户都有的 select *from ...
- ZOJ 2421 Recaman's Sequence
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1421 题目大意: 定义a^m为 a^m = a^(m-1) - m 如果a^ ...
- swift项目第八天:自定义转场动画以及设置titleView的状态
如图效果: 一:Home控制器 /* 总结:1:设置登陆状态下的导航栏的左右按钮:1:在viewDidLoad里用三目运算根据从父类继承的islogin的登陆标识来判断用户是否登陆来显示不同的界面.未 ...
- js进阶 12-7 pageY和screenY以及clientY的区别是什么
js进阶 12-7 pageY和screenY以及clientY的区别是什么 一.总结 一句话总结:pageY是距文件,screenY是获取显示器屏幕位置的坐标,clientY是页面视口. 没有滚动条 ...
- js进阶 11-22/23 js如何实现选项卡
js进阶 11-22/23 js如何实现选项卡 一.总结 一句话总结:通过索引把选项卡头的li标签和选项卡内容的div标签联系在一起,通过控制div标签的display属性可以实现选项卡的选项切换. ...
- JDK8 直接定义接口中静态方法
JDK8前,接口只能是抽象方法. 但是在JDK8中,静态方法是可以直接定义方法体,可以直接用接口名调用.实现类和实现是不可以调用的 一.直接调用接口的静态方法 二.实现接口的子类来调用接口的静态方法 ...
- python高级学习目录
1. Linux介绍.命令1.1. 操作系统(科普章节) 1.2. 操作系统的发展史(科普章节) 1.3. 文件和目录 1.4. Ubuntu 图形界面入门 1.5. Linux 命令的基本使用 1. ...
- Access Violations 访问冲突(AVs)是Windows编程时发生的最麻烦的错误?
Access Violations<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office&qu ...
- Android 在Service里面启动Activity
直接在代码: Intent dialogIntent = new Intent(getBaseContext(), YourActivity.class); dialogIntent.addFlags ...