UnitOfWork
Posted Leo_wlCnBlogs
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
运行看看
如期运行,到这里,工作单元就讲完了
完整项目架构
我们来看看完整的数据访问层架构
整个数据访问层就讲完了,虽然有些简陋,但是基本功能都有了
项目架构开发系列
- 项目架构开发:数据访问层之Cache
- 项目架构开发:数据访问层之Logger
- 项目架构开发:数据访问层之Query
- 项目架构开发:数据访问层之Repository
- 项目架构开发:数据访问层之UnitOfWork