在 ASP.NET Core 中使用 EF Core 进行开启事务工作单元(Unit of Work) 通用仓储层,通用服务层模式
在 ASP.NET Core 中实现一个通用的工作单元(Unit of Work)模式,配合通用仓储层和服务层,可以简化数据访问和业务逻辑。下面是如何实现这个模式的详细步骤。
- 定义实体类
首先,定义一个示例实体类,例如 Product:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}
- 定义数据库上下文
创建一个数据库上下文,继承自 DbContext:
public class ApplicationDbContext : DbContext
{
public DbSet<Product> Products { get; set; }
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
{
}
}
- 定义通用仓储接口和实现
创建通用仓储接口和其实现,以支持基本的 CRUD 操作:
public interface IRepository<T> where T : class
{
void Add(T entity);
void Update(T entity);
void Delete(T entity);
Task<T> GetByIdAsync(int id);
Task<IEnumerable<T>> GetAllAsync();
}
public class Repository<T> : IRepository<T> where T : class
{
private readonly ApplicationDbContext _context;
private readonly DbSet<T> _dbSet;
public Repository(ApplicationDbContext context)
{
_context = context;
_dbSet = context.Set<T>();
}
public void Add(T entity) => _dbSet.Add(entity);
public void Update(T entity) => _dbSet.Update(entity);
public void Delete(T entity) => _dbSet.Remove(entity);
public async Task<T> GetByIdAsync(int id) => await _dbSet.FindAsync(id);
public async Task<IEnumerable<T>> GetAllAsync() => await _dbSet.ToListAsync();
}
- 定义通用工作单元接口和实现
工作单元接口将支持事务处理:
public interface IUnitOfWork : IDisposable
{
IRepository<T> Repository<T>() where T : class;
Task<int> SaveChangesAsync();
Task BeginTransactionAsync();
Task CommitTransactionAsync();
Task RollbackTransactionAsync();
}
public class UnitOfWork : IUnitOfWork
{
private readonly ApplicationDbContext _context;
private IDbContextTransaction _transaction;
public UnitOfWork(ApplicationDbContext context)
{
_context = context;
}
public IRepository<T> Repository<T>() where T : class
{
return new Repository<T>(_context);
}
public async Task BeginTransactionAsync()
{
_transaction = await _context.Database.BeginTransactionAsync();
}
public async Task CommitTransactionAsync()
{
await _transaction.CommitAsync();
}
public async Task RollbackTransactionAsync()
{
await _transaction.RollbackAsync();
}
public async Task<int> SaveChangesAsync()
{
return await _context.SaveChangesAsync();
}
public void Dispose()
{
_context.Dispose();
}
}
- 创建通用服务层
实现通用服务层接口,提供业务逻辑处理:
public interface IService<T> where T : class
{
Task<T> CreateAsync(T entity);
Task<T> UpdateAsync(T entity);
Task<bool> DeleteAsync(int id);
Task<T> GetByIdAsync(int id);
Task<IEnumerable<T>> GetAllAsync();
}
public class Service<T> : IService<T> where T : class
{
private readonly IUnitOfWork _unitOfWork;
public Service(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
public async Task<T> CreateAsync(T entity)
{
await _unitOfWork.BeginTransactionAsync();
try
{
_unitOfWork.Repository<T>().Add(entity);
await _unitOfWork.SaveChangesAsync();
await _unitOfWork.CommitTransactionAsync();
}
catch
{
await _unitOfWork.RollbackTransactionAsync();
throw;
}
return entity;
}
public async Task<T> UpdateAsync(T entity)
{
await _unitOfWork.BeginTransactionAsync();
try
{
_unitOfWork.Repository<T>().Update(entity);
await _unitOfWork.SaveChangesAsync();
await _unitOfWork.CommitTransactionAsync();
}
catch
{
await _unitOfWork.RollbackTransactionAsync();
throw;
}
return entity;
}
public async Task<bool> DeleteAsync(int id)
{
await _unitOfWork.BeginTransactionAsync();
try
{
var entity = await _unitOfWork.Repository<T>().GetByIdAsync(id);
if (entity == null) return false;
_unitOfWork.Repository<T>().Delete(entity);
await _unitOfWork.SaveChangesAsync();
await _unitOfWork.CommitTransactionAsync();
}
catch
{
await _unitOfWork.RollbackTransactionAsync();
throw;
}
return true;
}
public async Task<T> GetByIdAsync(int id)
{
return await _unitOfWork.Repository<T>().GetByIdAsync(id);
}
public async Task<IEnumerable<T>> GetAllAsync()
{
return await _unitOfWork.Repository<T>().GetAllAsync();
}
}
- 在 Startup 类中注册服务
在 Startup.cs 中配置服务:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddScoped<IUnitOfWork, UnitOfWork>();
services.AddScoped(typeof(IService<>), typeof(Service<>));
}
- 使用服务层
创建控制器,通过依赖注入使用通用服务层:
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private readonly IService<Product> _productService;
public ProductsController(IService<Product> productService)
{
_productService = productService;
}
[HttpPost]
public async Task<IActionResult> Create(Product product)
{
var createdProduct = await _productService.CreateAsync(product);
return CreatedAtAction(nameof(GetById), new { id = createdProduct.Id }, createdProduct);
}
[HttpPut("{id}")]
public async Task<IActionResult> Update(int id, Product product)
{
if (id != product.Id) return BadRequest();
await _productService.UpdateAsync(product);
return NoContent();
}
[HttpGet("{id}")]
public async Task<IActionResult> GetById(int id)
{
var product = await _productService.GetByIdAsync(id);
if (product == null) return NotFound();
return Ok(product);
}
[HttpGet]
public async Task<ActionResult<IEnumerable<Product>>> GetAll()
{
var products = await _productService.GetAllAsync();
return Ok(products);
}
[HttpDelete("{id}")]
public async Task<IActionResult> Delete(int id)
{
var result = await _productService.DeleteAsync(id);
if (!result) return NotFound();
return NoContent();
}
}
总结
通过这种方式,我们实现了一个通用的工作单元、仓储和服务层架构。每个实体都可以重用同样的仓储和服务层逻辑,保持代码的简洁性和可维护性。
通用性:通过泛型设计,服务层和仓储层可以为任意实体类型提供支持。
事务控制:通过工作单元对每个操作进行事务控制,确保数据一致性。
清晰的结构:数据访问、业务逻辑和用户接口分离,使得代码更易于管理和维护。
你可以根据需求对上述代码和结构进一步扩展,例如添加更多的业务逻辑、错误处理和日志记录等功能