【ASP.NET CORE 项目实战(第五章)】Repository仓储 UnitofWork
简介
本章我们来创建仓储类Repository 并且引入 UnitOfWork
我对UnitOfWork的一些理解UnitOfWork 工作单元,对于这个的解释和实例,网上很多很多大神之作,我在这就不班门弄斧了,只是浅谈 一下个人理解,不一定对,希望大家指正:
UnitOfWork 看了很多,个人理解就是 统一事务,在很多操作中我们可能是进行多项操作的,比如 同时保存两个表的数据,如果我们先保存一个表(SaveChanges()之后),再保存另一个表(SaveChanges())其实是两个不同的事务,通俗的讲,我们对数据库提交了两次数据。而UnitOfWork 就是 把本次操作(分别保存两张表)放在统一事务中,所有的CRUD完成后,统一提交数据,即保证数据的一致性,又减少了提交次数,提高性能。
举个例子,我们之前的Repository的保存操作:
Repository: public virtual bool Save(T entity) { _Context.Add(entity); return _Context.SaveChanges() > 0; } Controller: public ActionResult Save() { var Users=new Users(){Id=1,UserName="张三"}; var Logs=new Logs(){log="注册了用户张三"}; _UserService.Save(Users); _LogService.Save(Logs); }
因为本身EF就是带事务的,但是_Context.SaveChanges()之后,事务就结束了,也提交了数据。所以,上面的例子 应该是开启了两次事务,提交了两次数据(一次是Users 一次是 Logs)
这显然是不合理的,首先不说提交两次数据性能的问题,如果用户注册失败,那么日志也不应该添加,应该回滚。但是,显然,上面没有这么做。
所以有了UnitOfWork。
使用UnitOfWork之后,代码应该是这样的:
UnitOfWork:
public bool Commit() { return _Context.SaveChanges() > 0; } Repository: public virtual bool Save(T entity) { _Context.Add(entity); } Controller: public ActionResult Save() { var Users=new Users(){Id=1,UserName="张三"}; var Logs=new Logs(){log="注册了用户张三"}; _UserService.Save(Users); _LogService.Save(Logs); _UnitOfWork.Commit(); }UnitOfWork接口和实现类
我们在wkmvc.Core类库下,新建一个接口IUnitOfWork:
1 namespace wkmvc.Core 2 { 3 /// 4 /// Describe:工作单元接口 5 /// Author:yuangang 6 /// Date:2016/07/16 7 /// Blogs:https://www.cnblogs.com/yuangang 8 /// 9 public interface IUnitOfWork 10 { 11 bool Commit(); 12 } 13 }
IUnitOfWork 实现类UnitOfWork:
1 using System; 2 using wkmvc.Data; 3 4 namespace wkmvc.Core 5 { 6 /// 7 /// Describe:工作单元实现类 8 /// Author:yuangang 9 /// Date:2016/07/16 10 /// Blogs:https://www.cnblogs.com/yuangang 11 /// 12 public class UnitOfWork : IUnitOfWork, IDisposable 13 { 14 #region 数据上下文 15 16 /// 17 /// 数据上下文 18 /// 19 private ApplicationDbContext _Context; 20 public UnitOfWork(ApplicationDbContext Context) 21 { 22 _Context = Context; 23 } 24 25 #endregion 26 27 public bool Commit() 28 { 29 return _Context.SaveChanges() > 0; 30 } 31 32 public void Dispose() 33 { 34 if(_Context!=null) 35 { 36 _Context.Dispose(); 37 } 38 GC.SuppressFinalize(this); 39 } 40 } 41 }
这样,UnitOfWork 就完成了。下面我们来添加仓储:
仓储 IRepository、Repository
新建接口IRepository添加基本的操作方法:
1 using System; 2 using System.Linq.Expressions; 3 4 namespace wkmvc.Core 5 { 6 /// 7 /// Describe:仓储接口 8 /// Author:yuangang 9 /// Date:2016/07/16 10 /// Blogs:https://www.cnblogs.com/yuangang 11 /// 12 /// 实体模型 13 public interface IRepository where T : class 14 { 15 #region 单模型 CRUD 操作 16 17 /// 18 /// 增加一条记录 19 /// 20 ///实体模型 21 ///是否提交(默认提交) 22 /// 23 bool Save(T entity, bool IsCommit = true); 24 25 /// 26 /// 更新一条记录 27 /// 28 ///实体模型 29 ///是否提交(默认提交) 30 /// 31 bool Update(T entity, bool IsCommit = true); 32 33 /// 34 /// 增加或更新一条记录 35 /// 36 ///实体模型 37 ///是否增加 38 ///是否提交(默认提交) 39 /// 40 bool SaveOrUpdate(T entity, bool IsSave, bool IsCommit = true); 41 42 /// 43 /// 通过Lamda表达式获取实体 44 /// 45 ///Lamda表达式(p=>p.Id==Id) 46 /// 47 T Get(Expression> predicate); 48 49 /// 50 /// 删除一条记录 51 /// 52 ///实体模型 53 ///是否提交(默认提交) 54 /// 55 bool Delete(T entity, bool IsCommit = true); 56 57 #endregion 58 } 59 }
实现类 Repository :
我们都添加了一个bool IsCommit = true 参数,是为了方便,如果仅仅是进行一项操作,那就没必要使用 UnitOfWork 统一 直接 SaveChanages() 就行了
我们来看下使用:
//第一种 public bool TestOne() { var users = new SYS_USER() { UserName="张三",Account="zhangsan",Password="123456" }; return _UserService.Save(users); } //第二种 public bool TestTwo() { var users1 = new SYS_USER() { UserName = "张三", Account = "zhangsan", Password = "123456" }; var users2 = new SYS_USER() { UserName = "李四", Account = "lisi", Password = "456789" }; var users3 = new SYS_USER() { UserName = "王五", Account = "wangwu", Password = "321654" }; _UserService.Save(users1); _UserService.Save(users2); _UserService.Save(users3); return _UnitOfWork.Commit(); }
本篇主要是介绍用法,具体的解释清大家参考大神们的讲解,如有不对的地方希望指正。具体的实现代码,我们后面一起一点一点写。