.net Core (UnitOfWork understanding)

Read the net and own corresponding understanding, just like summing up their own understanding, do not like spray! Based on EFcore 😀

1. Repository

Some basic add, delete, change and query operations can be placed in base classes

  • IRepository

    It’s a little bit easier to put the Guid primary key here and do general add, delete, and change

    * If all your tables are GUids

    public interface IRepository<TEntity>
    {
        / / check
        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>
    {
        / / to add authorization
        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);
    }
    Copy the code
  • 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)// Provide a choice
                {
                    _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; }}Copy the code

2. UnitOfWork

Provide transactions for services that require multiple Repository operations (EFcore’s SaveChanges() implements transactions by default)

  • IUnitOfWork

    public interface IUnitOfWork : IDisposable
    {
        void ExecuteProcedure(string procedureCommand, params object[] sqlParams);
        void ExecuteSql(string sql);
        List<T> SqlQuery<T> (string sql);
        int SaveChanges();
    }
    Copy the code
  • 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(); }}Copy the code

3. Dependency injection

Inject DbContext, UnitOfWork, and Repository in sequence.

Here we limit the DbContext and UnitOfWork lifecycles to Scoped to ensure that each request shares the same object

  • Startup.cs

    / / injection DbContext
    services.AddDbContext<DbContext>(
        options =>options.UseSqlServer(
        Configuration.GetConnectionString("DefaultConnection")));
    
    // Inject Uow dependencies
    services.AddScoped<IUnitOfWork, UnitOfWork<DbContext>>();
    
    // Inject the generic repository
    //services.AddTransient(typeof(IRepository<>), typeof(EfCoreRepository<>));
    //services.AddTransient(typeof(IRepository<,>), typeof(EfCoreRepository<,>));
    services.AddTransient(IUserRepository,UserRepository);
    services.AddTransient(ILedgerRepository,LedgerRepository);
    Copy the code

4. The application (Service)

  • Service

     public class Service : IService/ / omit 🙂...
     {
         
            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;
            }
         	// Multiple logical operations
         	public int logic()/ / operation
            {
                User user=new User();
                Ledger ledger=new Ledger();
                _userRepository.add(user,false);
                _ledgerRepository.add(ledger,false);
                return _unitOfWork.SaveChanges();
            }
         	public void logicOfAffair()// The design operation is single
            {
                User user=new User();
                _userRepository.add(user); }}Copy the code

5. To summarize

  • Is roughlyCommit all changes at once