【发布时间】:2021-03-10 22:02:18
【问题描述】:
根据 CQRS 模式,我有一个简单的命令,如下所示:
public sealed class EditPersonalInfoCommandHandler : ICommandHandler<EditPersonalInfoCommand> {
private readonly AppDbContext _context;
public EditPersonalInfoCommandHandler(AppDbContext context) {
_context = context;
}
public Result Handle(EditPersonalInfoCommand command) {
var studentRepo = new StudentRepository(_context);
Student student = studentRepo.GetById(command.Id);
if (student == null) {
return Result.Failure($"No Student found for Id {command.Id}");
}
student.Name = command.Name;
student.Email = command.Email;
_context.SaveChanges();
return Result.Success();
}
}
现在我需要尝试_context.SaveChanges() 最多 5 次,如果它因异常而失败。为此,我可以简单地在方法中有一个 for 循环:
for(int i = 0; i < 5; i++) {
try {
//required logic
} catch(SomeDatabaseException e) {
if(i == 4) {
throw;
}
}
}
要求是将方法作为单个单元执行。问题是一旦_context.SaveChanges() 抛出异常,就不能使用相同的_context 重新尝试逻辑。文档说:
丢弃当前的 DbContext。 创建一个新的 DbContext 并从数据库中恢复应用程序的状态。 通知用户上一次操作可能没有成功完成。
但是,在Startup.cs 中,我将AppDbContext 作为作用域依赖项。为了重新尝试方法逻辑,我需要一个 AppDbContext 的新实例,但注册为作用域不允许这样做。
我想到的一个解决方案是使AppDbContext 瞬态。但我有一种感觉,通过这样做,我将为自己打开一整套新问题。谁能帮帮我?
【问题讨论】:
-
确切的例外是什么?
-
@mjwills DbUpdateException 在 _context.SaveChanges() 失败时抛出。
标签: c# asp.net-core dependency-injection ef-core-5.0 resiliency