在 ASP.NET Core 中使用 EF Core 进行开启事务工作单元(Unit of Work) 通用仓储层,通用服务层模式

在 ASP.NET Core 中实现一个通用的工作单元(Unit of Work)模式,配合通用仓储层和服务层,可以简化数据访问和业务逻辑。下面是如何实现这个模式的详细步骤。

  1. 定义实体类
    首先,定义一个示例实体类,例如 Product:
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}
  1. 定义数据库上下文
    创建一个数据库上下文,继承自 DbContext:
public class ApplicationDbContext : DbContext
{
    public DbSet<Product> Products { get; set; }

    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
    {
    }
}
  1. 定义通用仓储接口和实现
    创建通用仓储接口和其实现,以支持基本的 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();
}
  1. 定义通用工作单元接口和实现
    工作单元接口将支持事务处理:
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();
    }
}
  1. 创建通用服务层
    实现通用服务层接口,提供业务逻辑处理:
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();
    }
}
  1. 在 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<>));
}
  1. 使用服务层
    创建控制器,通过依赖注入使用通用服务层:
[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();
    }
}

总结
通过这种方式,我们实现了一个通用的工作单元、仓储和服务层架构。每个实体都可以重用同样的仓储和服务层逻辑,保持代码的简洁性和可维护性。

通用性:通过泛型设计,服务层和仓储层可以为任意实体类型提供支持。
事务控制:通过工作单元对每个操作进行事务控制,确保数据一致性。
清晰的结构:数据访问、业务逻辑和用户接口分离,使得代码更易于管理和维护。
你可以根据需求对上述代码和结构进一步扩展,例如添加更多的业务逻辑、错误处理和日志记录等功能

posted @ 2024-10-29 17:33  一个人走在路上  阅读(115)  评论(0编辑  收藏  举报