数据访问仓储模式的事务管理(Unit of Work)
原创https://blog.csdn.net/huanghuangtongxue/article/details/79215136
1、定义IUnitOfWork接口
public interface IUnitOfWork { /// <summary> /// 提交更改 /// </summary> /// <returns></returns> int SaveChanges(); /// <summary> /// 提交更改异步 /// </summary> /// <returns></returns> Task<int> SaveChangesAsync(); /// <summary> /// 开启事务 /// </summary> void BeginTransaction(); /// <summary> /// 提交事务 /// </summary> void CommitTransaction(); /// <summary> /// 回滚事务 /// </summary> void RollBackTransaction(); }
2、定义 IUnitOfWork的实现类UnitOfWork,定义泛型TDBContext其类型必须是DbContext,通过构造函数依赖注入_dbContext
public class UnitOfWork<TDBContext> : IUnitOfWork where TDBContext : DbContext { private readonly TDBContext _dbContext; public UnitOfWork(TDBContext dbContext) { _dbContext = dbContext ?? throw new ArgumentNullException(nameof(dbContext)); } public int SaveChanges() { return _dbContext.SaveChanges(); } public async Task<int> SaveChangesAsync() { return await _dbContext.SaveChangesAsync(); } public void BeginTransaction() { _dbContext.Database.BeginTransaction(); } public void CommitTransaction() { _dbContext.Database.CommitTransaction(); } public void RollBackTransaction() { _dbContext.Database.RollbackTransaction(); } }
3、修改仓储的实现类,把 _dbContext.SaveChanges();这行代码全部删除。这样就不会每次更改就会提交,而是交由IUnitOfWork 统一的提交事务。
4、注册IUnitOfWork的时候要注意,要确保 UnitOfWork和DBContext 在整个请求中共用同一个对象,这样才能通过IUnitOfWork 来一次性提交事务。AddDbContext这个方法它默认的生命周期为ServiceLifetime.Scoped,所以只需要注册IUnitOfWork的时候使用AddScoped方法,将其生命周期限定为Scoped,就能保证每次请求都是共用同一个对象。
services.AddDbContext<YunSourseContext>(option => option.UseSqlServer(Configuration.GetConnectionString("Default"), b => b.UseRowNumberForPaging()));//配置sqlserver services.AddScoped<IUnitOfWork,UnitOfWork<YunSourseContext>>();//注入UOW依赖,确保每次请求都是同一个对象,生命周期Scope
5、调用_unitOfWork.SaveChanges();等等