在之前的泛型倉儲模式實現中,每個增刪改都調用了SaveChanges方法,導致每次更新都提交了事務。 在實際開發過程中,我們經常遇到同時操作多張表數據,那麼按照之前的寫法,對資料庫提交了多次操作,開啟了多事務,不能保證數據的一致性,結合工作單元(UnitOfWork)是為了把多次操作放到同一事務中, ...
在之前的泛型倉儲模式實現中,每個增刪改都調用了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(); } } }
遇到多倉儲持久化操作時,用構造函數依賴註入相應的倉儲即可。