Entity Framework Core 中使用仓库和工作单元事务,服务层和控制器

在 ASP.NET Core 中,使用工作单元模式(Unit of Work)可以有效地管理数据库事务。通过定义一个能够开启、提交和回滚事务的工作单元接口及其实现,结合仓储层和服务层,可以让数据操作更加清晰和可靠。以下是详细说明。

  1. 定义工作单元接口 IUnitOfWork
    该接口将包含开启、提交和回滚事务的方法:
public interface IUnitOfWork : IDisposable
{
Task BeginTransactionAsync();
Task CommitAsync();
Task RollbackAsync();
Task<int> SaveChangesAsync();
}
  1. 实现工作单元类 UnitOfWork
    在实现类中,我们需要使用 DbContext 来控制数据库操作,并管理事务的开启、提交和回滚:
public class UnitOfWork : IUnitOfWork
{
private readonly AppDbContext _context;
private IDbContextTransaction _transaction;
public UnitOfWork(AppDbContext context)
{
_context = context;
}
public async Task BeginTransactionAsync()
{
_transaction = await _context.Database.BeginTransactionAsync();
}
public async Task CommitAsync()
{
await _context.SaveChangesAsync();
await _transaction.CommitAsync();
}
public async Task RollbackAsync()
{
await _transaction.RollbackAsync();
}
public async Task<int> SaveChangesAsync()
{
return await _context.SaveChangesAsync();
}
public void Dispose()
{
_transaction?.Dispose();
_context?.Dispose();
}
}
  1. 定义仓储接口 IRepository
    与之前相同,定义仓储接口以提供 CRUD 操作:
public interface IRepository<T> where T : class
{
Task<IEnumerable<T>> GetAllAsync();
Task<T> GetByIdAsync(int id);
Task AddAsync(T entity);
Task UpdateAsync(T entity);
Task DeleteAsync(int id);
}
  1. 实现仓储类 Repository
    实现该接口,使数据访问更为简单:
public class Repository<T> : IRepository<T> where T : class
{
private readonly AppDbContext _context;
private readonly DbSet<T> _dbSet;
public Repository(AppDbContext context)
{
_context = context;
_dbSet = context.Set<T>();
}
public async Task<IEnumerable<T>> GetAllAsync()
{
return await _dbSet.ToListAsync();
}
public async Task<T> GetByIdAsync(int id)
{
return await _dbSet.FindAsync(id);
}
public async Task AddAsync(T entity)
{
await _dbSet.AddAsync(entity);
}
public async Task UpdateAsync(T entity)
{
_dbSet.Update(entity);
}
public async Task DeleteAsync(int id)
{
var entity = await GetByIdAsync(id);
if (entity != null)
{
_dbSet.Remove(entity);
}
}
}
  1. 定义服务层接口 IProductService
    服务层接口用于业务逻辑的处理:
public interface IProductService
{
Task<IEnumerable<Product>> GetAllProductsAsync();
Task<Product> GetProductByIdAsync(int id);
Task AddProductAsync(Product product);
Task UpdateProductAsync(Product product);
Task DeleteProductAsync(int id);
}
  1. 实现服务层类 ProductService
    在服务层中包含事务控制:
public class ProductService : IProductService
{
private readonly IRepository<Product> _productRepository;
private readonly IUnitOfWork _unitOfWork;
public ProductService(IRepository<Product> productRepository, IUnitOfWork unitOfWork)
{
_productRepository = productRepository;
_unitOfWork = unitOfWork;
}
public async Task<IEnumerable<Product>> GetAllProductsAsync()
{
return await _productRepository.GetAllAsync();
}
public async Task<Product> GetProductByIdAsync(int id)
{
return await _productRepository.GetByIdAsync(id);
}
public async Task AddProductAsync(Product product)
{
await _unitOfWork.BeginTransactionAsync();
try
{
await _productRepository.AddAsync(product);
await _unitOfWork.SaveChangesAsync();
await _unitOfWork.CommitAsync();
}
catch
{
await _unitOfWork.RollbackAsync();
throw; // 重新抛出异常以便于上层处理
}
}
public async Task UpdateProductAsync(Product product)
{
await _unitOfWork.BeginTransactionAsync();
try
{
await _productRepository.UpdateAsync(product);
await _unitOfWork.SaveChangesAsync();
await _unitOfWork.CommitAsync();
}
catch
{
await _unitOfWork.RollbackAsync();
throw;
}
}
public async Task DeleteProductAsync(int id)
{
await _unitOfWork.BeginTransactionAsync();
try
{
await _productRepository.DeleteAsync(id);
await _unitOfWork.SaveChangesAsync();
await _unitOfWork.CommitAsync();
}
catch
{
await _unitOfWork.RollbackAsync();
throw;
}
}
}
  1. 创建控制器 ProductsController
    控制器处理 HTTP 请求并调用服务层的方法:
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private readonly IProductService _productService;
public ProductsController(IProductService productService)
{
_productService = productService;
}
[HttpGet]
public async Task<IActionResult> GetAll()
{
var products = await _productService.GetAllProductsAsync();
return Ok(products);
}
[HttpGet("{id}")]
public async Task<IActionResult> GetById(int id)
{
var product = await _productService.GetProductByIdAsync(id);
return product != null ? Ok(product) : NotFound();
}
[HttpPost]
public async Task<IActionResult> Create(Product product)
{
await _productService.AddProductAsync(product);
return CreatedAtAction(nameof(GetById), new { id = product.Id }, product);
}
[HttpPut("{id}")]
public async Task<IActionResult> Update(int id, Product product)
{
if (id != product.Id)
{
return BadRequest();
}
await _productService.UpdateProductAsync(product);
return NoContent();
}
[HttpDelete("{id}")]
public async Task<IActionResult> Delete(int id)
{
await _productService.DeleteProductAsync(id);
return NoContent();
}
}

总结
通过以上步骤,您已经成功实现了一个带有事务控制的工作单元接口及其实现类,同时定义了仓储层和服务层的结构,控制器也进行了相应的适配。这样的设计可以有效地管理和维护数据库事务,提高代码的健壮性与清晰度。

posted @   一个人走在路上  阅读(85)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构
点击右上角即可分享
微信分享提示