c# - 如何在 .NET 中使用 CQRS 模式 mediatr 使 EF 事务化?
问题描述
假设我有CreateProductCommandHandler:
public class CreateProductCommandHandler : IRequestHandler<CreateProductCommand, Guid>
{
private readonly IProductRepository _productRepository;
private readonly IProductCategoryRepository _productCategoryRepository;
private readonly IMapper _mapper;
private readonly IEmailService _emailService;
public CreateProductCommandHandler(IEmailService emailService, IProductRepository productRepository, IMapper mapper, IProductCategoryRepository productCategoryRepository)
{
_mapper = mapper;
_productRepository = productRepository;
_emailService = emailService;
_productCategoryRepository = productCategoryRepository;
}
public async Task<Guid> Handle(CreateProductCommand request, CancellationToken cancellationToken)
{
var validator = new CreateProductCommandValidator(_productRepository);
var validationResult = await validator.ValidateAsync(request);
if (validationResult.Errors.Count > 0)
throw new Exceptions.ValidationException(validationResult);
var @product = _mapper.Map<Product>(request);
@product = await _productRepository.AddAsync(@product);
var @productCategory = new ProductCategory();
@productCategory.ProductID = @product.ProductID;
foreach (var cat in request.listOfCategories)
{
@productCategory.CategoryID = cat.CategoryID;
await _productCategoryRepository.AddAsync(@productCategory);
}
return @product.Uid;
}
}
当我使用两个存储库时,可能会出现在这一行
等待 _productCategoryRepository.AddAsync(@productCategory);
有些事情失败了,所以我需要对整个事务进行回滚。由于我是 CQRS mediatr 的新手,有人有想法和最好的方法来做到这一点吗?
解决方案
如果这一切都在一个处理程序的范围内。最简单的解决方案是注入 DbContext 并创建一个包含所有存储库调用的事务,如下所示。
public class CreateProductCommandHandler : IRequestHandler<CreateProductCommand, Guid>
{
private readonly IProductRepository _productRepository;
private readonly IProductCategoryRepository _productCategoryRepository;
private readonly SomeDbContext _dbContext;
private readonly IMapper _mapper;
private readonly IEmailService _emailService;
public CreateProductCommandHandler(IEmailService emailService, IProductRepository productRepository, IMapper mapper, IProductCategoryRepository productCategoryRepository, SomeDbContext dbContext)
{
_mapper = mapper;
_productRepository = productRepository;
_emailService = emailService;
_productCategoryRepository = productCategoryRepository;
_dbContext = dbContext;
}
public async Task<Guid> Handle(CreateProductCommand request, CancellationToken cancellationToken)
{
var validator = new CreateProductCommandValidator(_productRepository);
var validationResult = await validator.ValidateAsync(request);
if (validationResult.Errors.Count > 0)
throw new Exceptions.ValidationException(validationResult);
var @product = _mapper.Map<Product>(request);
await using var transaction = await _dbContext.Database.BeginTransactionAsync();
@product = await _productRepository.AddAsync(@product);
var @productCategory = new ProductCategory();
@productCategory.ProductID = @product.ProductID;
foreach (var cat in request.listOfCategories)
{
@productCategory.CategoryID = cat.CategoryID;
await _productCategoryRepository.AddAsync(@productCategory);
}
await transaction.CommitAsync();
return @product.Uid;
}
}
如果在您调用 CommitAsync() 之前发生异常,事务将被释放并发生回滚。
推荐阅读
- php - 以编程方式发送 eth php
- javascript - Redux:dispatch(...).then 不是函数
- mysql - Mysql插入顺序
- numpy - GDAL 2.3.1 已安装,但 llinux 终端正在使用 GDAL 2.2.2
- python-3.x - 我想在 python 中迭代我的一组按钮点击
- error-handling - 创建使用 try 运算符的闭包时,如何修复错误“需要类型注释”?
- csrf - 带有正则表达式模式的 Tomcat 8.52 版本 CsrfPreventionFilter entryPoints 参数
- node.js - module.js:549 抛出错误;错误:找不到模块 './models/TodoListModel' Nodemon 在添加模型文件时显示此错误
- android - 跟踪每个用户在 Android 应用程序中每天单击按钮多少次的最佳方法?
- corda - 我可以在 Corda oracle 服务中使用依赖注入吗?