在之前的泛型仓储模式实现中,每个增删改都调用了SaveChanges方法,导致每次更新都提交了事务。
在实际开发过程中,我们经常遇到同时操作多张表数据,那么按照之前的写法,对数据库提交了多次操作,开启了多事务,不能保证数据的一致性,结合工作单元(UnitOfWork)是为了把多次操作放到同一事务中,要么都成功(Commit),要么都失败(Rollback),保证了数据的一致性。
修改仓储类
先把仓储接口中增删改接口无返回(void)值类型,然后去仓储实现类去掉SaveChanges方法,交给UOW统一处理
实现UOW
把SaveChanges抽离出来,定义IUnitOfWork接口
namespace NetCoreWebApi.Repository { /// <summary> /// 接口 /// </summary> public interface IUnitOfWork { /// <summary> /// 保存 /// </summary> /// <returns></returns> int SaveChanges(); } }
实现IUnitOfWork接口
using System; using Microsoft.EntityFrameworkCore; namespace NetCoreWebApi.Repository { /// <summary> /// 实现类 /// </summary> public class UnitOfWork<TDbContext> : IUnitOfWork where TDbContext : DbContext { /// <summary> /// dbContext上下文 /// </summary> private readonly TDbContext _dbContext; /// <summary> /// 构造函数 /// </summary> /// <param name="dbContext"></param> public UnitOfWork(TDbContext dbContext) { _dbContext = dbContext; } /// <summary> /// 保存 /// </summary> public int SaveChanges() { int code; try { code = _dbContext.SaveChanges(); } catch (DbUpdateException e) { throw new Exception(e.InnerException == null ? e.Message : e.InnerException.Message); } return code; } } }
UOW依赖注入
因为AddDbContext默认生命周期是Scoped,所以用AddScoped注册UOW,确保每次请求共用同一个DbContex对象。
//注入DbContext services.AddDbContext<MyDbContext> (options => options.UseSqlServer(connectionStr,e => e.MigrationsAssembly("NetCoreWebApi.Model"))); //注入Uow依赖 services.AddScoped<IUnitOfWork, UnitOfWork<MyDbContext>>();
使用UOW
修改UserRepository业务层
using System.Collections.Generic; using System.Linq; using NetCoreWebApi.Model.Models; using NetCoreWebApi.Repository.Interface; using NetCoreWebApi.Repository.Repository; namespace NetCoreWebApi.Repository.Implement { /// <summary> /// 业务处理 /// </summary> public class UserRepository:IUserRepository { private readonly IUnitOfWork _unitOfWork; private readonly IRepository<TbUser> _userRepository; /// <summary> /// 构造函数 /// </summary> /// <param name="userRepository"></param> /// <param name="unitOfWork"></param> public UserRepository(IRepository<TbUser> userRepository,IUnitOfWork unitOfWork) { _userRepository = userRepository; _unitOfWork = unitOfWork; } /// <summary> /// 添加用户 /// </summary> /// <param name="entity"></param> /// <returns></returns> public int Add(TbUser entity) { _userRepository.Add(entity); return _unitOfWork.SaveChanges(); } /// <summary> /// 删除用户 /// </summary> /// <param name="entity"></param> /// <returns></returns> public int Remove(TbUser entity) { _userRepository.Remove(entity); return _unitOfWork.SaveChanges(); } /// <summary> /// 查询用户 /// </summary> /// <returns></returns> public IList<TbUser> GetAll() { return _userRepository.GetAll().ToList(); } } }
遇到多仓储持久化操作时,用构造函数依赖注入相应的仓储即可。