UnitOfWork

Posted Leo_wlCnBlogs

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UnitOfWork相关的知识,希望对你有一定的参考价值。

接上文 项目架构开发:数据访问层之IQuery

 

本章我们继续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的主要内容,如果未能解决你的问题,请参考以下文章

EF + UnitOfWork + SharePoint RunWithElevatedPrivileges

[Doctrine2] 刷新失败但 unitOfWork 进程正确

UnitOfWork + Repository 模式和实体框架模拟

UnitOfWork 是不是等于事务?还是不止于此?

无法模拟unitOfWork和没有服务接口

.NetCore基于SqlSugar的工作单元—UnitOfWork