简体   繁体   English

.Net Core Entity Framework Generic Repository Pattern - 使用 UnitOfWork 实现共享服务

[英].Net Core Entity Framework Generic Repository Pattern - Implement Shared Service With UnitOfWork

I want to use Shared Service that include some common methods like create, update, delete in my business layer.我想在我的业务层中使用包含一些常用方法的共享服务,如创建、更新、删除。 I have already implemented repository and unit of work classes but I encountered some problems while trying to create a shared service.我已经实现了存储库和工作单元类,但是在尝试创建共享服务时遇到了一些问题。 Lets assume that we have a non-shared create method like this:让我们假设我们有一个像这样的非共享创建方法:

public class ProductService : IProductService
{
    private readonly IUnitOfWork _unitOfWork;
    public ProductService(IUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }
    public async Task<Product> CreateProduct(Product newProduct)
    {
        await _unitOfWork.Products.AddAsync(newProduct);
        await _unitOfWork.CommitAsync();
        return newProduct;
    }
}

The part that confuses me in the above code is, I call my UnitOfWork with _unitOfWork.Product command, how do we convert it to unitOfWork.TEntity to make generic?上面代码中让我感到困惑的部分是,我用 _unitOfWork.Product 命令调用我的 UnitOfWork,我们如何将它转换为 unitOfWork.TEntity 以使其通用? Is it possible?可能吗? In this case, I tried doing generic but I guess there is no such thing as _unitOfWork.TEntity.在这种情况下,我尝试做泛型,但我想没有 _unitOfWork.TEntity 这样的东西。 I just need to edit the Service class, I add other related classes to give extra information.我只需要编辑服务 class,我添加其他相关类以提供额外信息。

Service:服务:

    public class Service<TEntity>: IService<TEntity> where TEntity : class
    {
        private readonly IUnitOfWork _unitOfWork;
        public Service(IUnitOfWork unitOfWork)
        {
            _unitOfWork = unitOfWork;
        }
        public async Task<TEntity> AddAsync(TEntity entity)
        {
            await _unitOfWork.TEntity.AddAsync(entity);
            await _unitOfWork.CommitAsync();
            return entity;
        }
    }

IService:服务:

    public interface IService<TEntity> where TEntity : class
    {
        Task<TEntity> AddAsync(TEntity entity);
    }

Repository:存储库:

    public abstract class Repository<TEntity> : IRepository<TEntity> where TEntity : class
    {
        private readonly DbContext _context;
        private readonly DbSet<TEntity> _dbSet;

        public Repository(ECommerceDbContext context)
        {
            _context = context;
            _dbSet = context.Set<TEntity>();
        }

        public async Task<TEntity> AddAsync(TEntity entity)
        {
            entity.CreateDate = DateTime.Now;
            await _dbSet.AddAsync(entity);
            await SaveAsync();
            return entity;
        }

        public async Task AddAsync(IEnumerable<TEntity> entities)
        {
            foreach (var item in entities)
            {
                await AddAsync(item);
            }
        }

        public async Task<bool> AnyAsync(Expression<Func<TEntity, bool>> expression)
        {
            return await _dbSet.AnyAsync(expression);
        }

        public async Task<bool> AnyAsync()
        {
            return await AnyAsync(x => true);
        }

        public async Task<long> CountAsync()
        {
            return await CountAsync(x => true);
        }

        public async Task<long> CountAsync(Expression<Func<TEntity, bool>> expression)
        {
            return await _dbSet.LongCountAsync(expression);
        }

        public void Delete(TEntity model)
        {
            _dbSet.Remove(model);
        }

        public async Task DeleteAsync(int id)
        {
            var entity = await GetAsync(id);
            Delete(entity);
        }

        public async Task<TEntity> FirstOrDefault(Expression<Func<TEntity, bool>> expression)
        {
            return await _dbSet.FirstOrDefaultAsync(expression);
        }

        public async Task<TEntity> GetAsync(int id)
        {
            return await FirstOrDefault(x => x.Id == id);
        }

        public async Task<IEnumerable<TEntity>> GetAll()
        {
            return await _dbSet.ToListAsync();
        }

        public async Task SaveAsync()
        {
           await _context.SaveChangesAsync();
        }

        public async Task<TEntity> Update(TEntity entity)
        {
            var temp = GetAsync(entity.Id);
            entity.UpdateDate = DateTime.Now;
            _context.Entry(temp).CurrentValues.SetValues(entity);
            await SaveAsync();
            return await temp;
        }
    }

IRepository:存储库:

    public interface IRepository<TEntity> where TEntity :class
    {
        Task<TEntity> AddAsync(TEntity entity);
        Task AddAsync(IEnumerable<TEntity> entities);
        Task<bool> AnyAsync(Expression<Func<TEntity, bool>> expression);
        Task<bool> AnyAsync();
        Task<long> CountAsync();
        Task<long> CountAsync(Expression<Func<TEntity, bool>> expression);
        void Delete(TEntity model);
        Task DeleteAsync(int id);
        Task<TEntity> FirstOrDefault(Expression<Func<TEntity, bool>> expression);
        Task<TEntity> GetAsync(int id);
        Task<IEnumerable<TEntity>> GetAll();
        Task SaveAsync();
        Task<TEntity> Update(TEntity entity);
    }

UnitOfWork:工作单位:

    public class UnitOfWork:IUnitOfWork
    {
        private readonly ECommerceDbContext _context;
        private ProductRepository _productRepository;

        public UnitOfWork(ECommerceDbContext context)
        {
            _context = context;
        }

        public IProductRepository Products => _productRepository = _productRepository ?? new ProductRepository(_context);

        public async Task<int> CommitAsync()
        {
            return await _context.SaveChangesAsync();
        }

        public void Dispose()
        {
            _context.Dispose();
        }
    }
IUnitOfWork

    public interface IUnitOfWork : IDisposable
    {
        IProductRepository Products { get; }
        Task<int> CommitAsync();
    }

Service TEntity: class.. I think here class is TEntity: Entity.服务TEntity:class ..我认为这里的class是TEntity:Entity。

It's helpful if you share your 'IProductRepository' and ProductRepository objects.如果您共享您的“IProductRepository”和 ProductRepository 对象,这将很有帮助。

public interface IService<TEntity> where TEntity : Entity
{
    Task<TEntity> AddAsync(TEntity entity);
}

public class Service<TEntity> : IService<TEntity> where TEntity : Entity
{
    private readonly IUnitOfWork _unitOfWork;
    public Service(IUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }
    public async Task<TEntity> AddAsync(TEntity entity)
    {
        //await _unitOfWork.TEntity.AddAsync(entity);
        await _unitOfWork.Products.AddAsync(entity);
        await _unitOfWork.CommitAsync();
        return entity;
    }
}

public class ProductService : Service<Product>,IProductService
{
    public ProductService(IUnitOfWork unitOfWork):base(unitOfWork)
    {

    }
}

public class UnitOfWork : IUnitOfWork
{
    private readonly ECommerceDbContext _context;
    private IProductRepository _productRepository;

    public UnitOfWork(ECommerceDbContext context)
    {
        _context = context;
    }

    public IProductRepository Products => _productRepository = _productRepository ?? new ProductRepository(_context);

    public async Task<int> CommitAsync()
    {
        return await _context.SaveChangesAsync();
    }

    public void Dispose()
    {
        _context.Dispose();
    }
}

Because each entity type is a strongly typed object, you cannot genericize your implementation without reflection.因为每个实体类型都是强类型的 object,所以如果没有反射,就无法泛化您的实现。 A common workaround is to provide a generic callback while allowing the invoker to provide the specific mapping per entity type.一个常见的解决方法是提供一个通用回调,同时允许调用者提供每个实体类型的特定映射。

public class Service<TEntity> : IService<TEntity> where TEntity : class
{
    private readonly IUnitOfWork _unitOfWork;
    public Service(IUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }
    
    public async Task<TEntity> AddAsync(TEntity entity, 
        Func<TEntity, IUnitOfWork, Task> addEntityCallback)
    {
        await addEntityCallback(entity, _unitOfWork);
        await _unitOfWork.CommitAsync();
        return entity;
    }
}

public interface IService<TEntity> where TEntity : class
{
    Task<TEntity> AddAsync(TEntity entity, Func<TEntity, IUnitOfWork, Task> addEntityCallback);
}

You can then call IService.AddAsync with a specific mapping:然后,您可以使用特定映射调用IService.AddAsync

public class ProductService : IProductService
{
    private readonly IService<Product> _service;
    public ProductService(IService<Product> service)
    {
        _service = service;
    }

    public async Task<Product> CreateProduct(Product newProduct)
    {
        await _service.AddAsync(newProduct, 
            (entity, unitOfWork) => unitOfWork.Products.AddAsync(entity));
        return newProduct;
    }
}

Update: in the case where you want to always inherit Service<TEntity> (per your comment), you could use an abstract method that functions in a similar manner to a callback parameter.更新:如果您希望始终继承Service<TEntity> (根据您的评论),您可以使用一个抽象方法,该方法以类似于回调参数的方式运行。 This allows you to still encapsulate the logic in the ProductService but now no longer requires you to provide a create method.这允许您仍然将逻辑封装在ProductService中,但现在不再需要您提供 create 方法。

public class ProductService : Service<Product>, IProductService
{
    public ProductService(IUnitOfWork unitOfWork) : base(unitOfWork)
    {
    }

    protected override async Task<Product> AddEntityCallback(Product entity, 
        IUnitOfWork unitOfWork)
    {
        await unitOfWork.Products.AddAsync(entity);
        return entity;
    }
}

public abstract class Service<TEntity> : IService<TEntity> where TEntity : class
{
    private readonly IUnitOfWork _unitOfWork;
    public Service(IUnitOfWork unitOfWork)
    {
        _unitOfWork = unitOfWork;
    }

    protected abstract Task<TEntity> AddEntityCallback(TEntity entity, 
        IUnitOfWork unitOfWork);
    
    public async Task<TEntity> AddAsync(TEntity entity)
    {
        await AddEntityCallback(entity, _unitOfWork);
        await _unitOfWork.CommitAsync();
        return entity;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM