对 UnitOfWork 简单理解

1,666 阅读2分钟

.Net Core (UnitOfWork理解)

看了网上和自己对应的理解,就像总结一下自己的理解,不喜勿喷!😀,基于EFcore

1. Repository

一些基本的增删改查操作可以放在基类

  • IRepository

    这里省事一点可以把Guid 主键放在这里做通用的增删改

    *如果你们数据表 都是Guid的话

    public interface IRepository<TEntity>
    {
        //查
        IQueryable<TEntity> Where(Expression<Func<TEntity, bool>> expression);
        Task<bool> AnyAsync(Expression<Func<TEntity, bool>> expression);
    }
    public interface IRepository<TEntity, in TKey> : IRepository<TEntity> where TEntity : Entity<TKey>
    {
        //增删改
        void Add(TEntity entity);
        TEntity Get(TKey id);
        void Update(TEntity entity,bool IsCommit=true);
        bool Remove(TEntity entity,bool IsCommit=true);
        bool Delete(TKey id,bool IsCommit=true);
    }
    
  • Repository

    public class Repository<TEntity,TKey> :  IRepository<TEntity, TKey>
            where TEntity : Entity<TKey> where TDbContext : EfContext
            {
                private readonly UnitOfWork _UnitOfWork;
                private readonly DBContext _dbContext 
                public Repository(TDbContext dbContext,IUnitOfWork unitOfWork)//提供一个选择
                {
                    _dbContext = dbContext;
                    _UnitOfWork = unitOfWork;
                }
                public IQueryable<TEntity> Where(Expression<Func<TEntity, bool>> expression)
                {
                    return _dbContext.Set<TEntity>().AsNoTracking().Where(expression);
                }
                public bool Any(Expression<Func<TEntity, bool>> expression)
                {
                    return _dbContext.Set<TEntity>().AsNoTracking().Any(expression);
                }
                public virtual TEntity Get(TKey id)
                {
                    try
                    {
                        return _dbContext.Set<TEntity>().AsNoTracking().FirstOrDefault(x => x.Id.ToString() == id.ToString());
                    }
                    catch (Exception e)
                    {
                        return null;
                    }
    
                }
                public void Add(TEntity entity,bool IsCommit=true)
                {
                    _dbContext.Add(entity);
                    if(IsCommit)
                    	_dbContext.SaveChanges();
                }
                public void Update(TEntity entity,bool IsCommit=true)
                {
                    var entity = dbContext.Find<TEntity>(new object[]{entity.Id});
                    var res = dbContext.Set<TEntity>().Update(entity).Entity;
                    if(IsCommit)
                    	dbContext.SaveChanges();
                }
                public bool Delete(TKey id,bool IsCommit=true)
                {
                    using var dbContext = _dbContextFactory();
                    var entity = dbContext.Find<TEntity>(id);
                    if (entity == null)
                    {
                        return false;
                    }
                    dbContext.Remove(entity);
                    if(IsCommit)
                    	dbContext.SaveChanges();
                    return true;
                }
            }            
    

2. UnitOfWork

对需要多个Repository仓储操作的service 提供事务操作(EFcore 的SaveChanges()默认实现事务)

  • IUnitOfWork

    public interface IUnitOfWork : IDisposable
    {
        void ExecuteProcedure(string procedureCommand, params object[] sqlParams);
        void ExecuteSql(string sql);
        List<T> SqlQuery<T>(string sql);
        int SaveChanges();
    }
    
  • UnitOfWork

    public class UnitOfWork<DbContext> : IUnitOfWork where DbContext : DbContext 
    {
        protected readonly DbContext _context;
    
        public UnitOfWork(DbContext context)
        {
            _context = context;
        }
        public int SaveChanges()
        {
            return _context.SaveChanges();
        }
    }
    

3.依赖注入

依次注入DbContext、UnitOfWork和Repository.

这里我们限定了DbContext和UnitOfWork的生命周期为Scoped,从而确保每次请求共用同一个对象

  • Startup.cs

    //注入DbContext
    services.AddDbContext<DbContext>(
        options =>options.UseSqlServer(
        Configuration.GetConnectionString("DefaultConnection")));
    
    //注入Uow依赖
    services.AddScoped<IUnitOfWork, UnitOfWork<DbContext>>();
    
    //注入泛型仓储
    //services.AddTransient(typeof(IRepository<>), typeof(EfCoreRepository<>));
    //services.AddTransient(typeof(IRepository<,>), typeof(EfCoreRepository<,>));
    services.AddTransient(IUserRepository,UserRepository);
    services.AddTransient(ILedgerRepository,LedgerRepository);
    

4. 应用(Service)

  • Service

     public class Service : IService//省略🙂...
     {
         
            private readonly IUserRepository _userRepository;
            private readonly ILedgerRepository _ledgerRepository;
         	private readonly IUnitOfWork  _unitOfWork;
         	public Service(IUnitOfWork unitOfWork,IUserRepository userRepository, 
                ILedgerRepository ledgerRepository)
            {
                _unitOfWork=unitOfWork;
                _userRepository = userRepository;
                _ledgerRepository = ledgerRepository;
            }
         	//多逻辑操作
         	public int logic()//多操作
            {
                User user=new User();
                Ledger ledger=new Ledger();
                _userRepository.add(user,false);
                _ledgerRepository.add(ledger,false);
                return _unitOfWork.SaveChanges();
            }
         	public void logicOfAffair()//设计操作单一
            {
                User user=new User();
                _userRepository.add(user);
            }
     }
    

5. 总结

  • 大致就是一次性提交所有更改