.Net Core Entity Framework 通用存储库模式 - 使用 UnitOfWork 实现共享服务
.Net Core Entity Framework Generic Repository Pattern - Implement Shared Service With UnitOfWork
我想在我的业务层中使用包含一些常用方法(如创建、更新、删除)的共享服务。我已经实现了存储库和工作单元 classes,但是我在尝试创建共享服务时遇到了一些问题。假设我们有一个像这样的非共享创建方法:
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;
}
}
上面代码中让我感到困惑的部分是,我用 _unitOfWork.Product 命令调用我的 UnitOfWork,我们如何将它转换为 unitOfWork.TEntity 以使其通用?可能吗?在这种情况下,我尝试使用泛型,但我猜不存在 _unitOfWork.TEntity 这样的东西。我只需要编辑服务 class,我添加其他相关 class 以提供额外信息。
服务:
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;
}
}
我服务:
public interface IService<TEntity> where TEntity : class
{
Task<TEntity> AddAsync(TEntity entity);
}
存储库:
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);
}
工作单位:
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 .. 我认为这里 class 是 TEntity : Entity.
共享 '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();
}
}
因为每个实体类型都是强类型对象,所以您不能在没有反射的情况下泛型化您的实现。一个常见的解决方法是提供通用回调,同时允许调用者为每个实体类型提供特定映射。
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);
}
然后您可以使用特定映射调用 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;
}
}
更新: 如果您想始终继承 Service<TEntity>
(根据您的评论),您可以使用一种抽象方法,其功能类似于回调参数。这允许您仍然将逻辑封装在 ProductService
中,但现在不再需要您提供创建方法。
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;
}
}
我想在我的业务层中使用包含一些常用方法(如创建、更新、删除)的共享服务。我已经实现了存储库和工作单元 classes,但是我在尝试创建共享服务时遇到了一些问题。假设我们有一个像这样的非共享创建方法:
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;
}
}
上面代码中让我感到困惑的部分是,我用 _unitOfWork.Product 命令调用我的 UnitOfWork,我们如何将它转换为 unitOfWork.TEntity 以使其通用?可能吗?在这种情况下,我尝试使用泛型,但我猜不存在 _unitOfWork.TEntity 这样的东西。我只需要编辑服务 class,我添加其他相关 class 以提供额外信息。
服务:
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;
}
}
我服务:
public interface IService<TEntity> where TEntity : class
{
Task<TEntity> AddAsync(TEntity entity);
}
存储库:
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);
}
工作单位:
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 .. 我认为这里 class 是 TEntity : Entity.
共享 '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();
}
}
因为每个实体类型都是强类型对象,所以您不能在没有反射的情况下泛型化您的实现。一个常见的解决方法是提供通用回调,同时允许调用者为每个实体类型提供特定映射。
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);
}
然后您可以使用特定映射调用 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;
}
}
更新: 如果您想始终继承 Service<TEntity>
(根据您的评论),您可以使用一种抽象方法,其功能类似于回调参数。这允许您仍然将逻辑封装在 ProductService
中,但现在不再需要您提供创建方法。
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;
}
}