Sho*_*hoe 7 .net c# transactions entity-framework-core .net-core
假设我有一个执行以下操作的控制器操作:
简单的实现存在多个问题:
解决这些问题的方法似乎是使用SERIALIZABLE事务隔离级别。问题在于,每个人似乎都认为此事务隔离级别非常危险,因为它可能导致死锁。
给出以下简单的解决方案:
public class AController
{
// ...
public async Task Fn(..., CancellationToken cancellationToken)
{
var calendarSlotExists = dbContext.Slots.Where(...).AnyAsync(cancellationToken);
var appointmentsAreOverlapping = dbContext.Appointments.Where(...).AnyAsync(cancellationToken);
if (calendarSlotExists && !appointmentsAreOverlapping)
dbContext.Appointments.Add(...);
dbContext.SaveChangesAsync(cancellationToken);
}
}
Run Code Online (Sandbox Code Playgroud)
始终防止并发问题的最佳方法是什么?我应该如何处理最终的死锁?
数据库完整性检查是您最好的朋友
根据您的描述,您的预约是基于时段的。这使得问题变得更加简单,因为您可以有效地为表定义唯一SlotId约束Appointments。然后你需要一个外键作为Appointments.SlotId参考Slot.Id
如果在步骤 3 之前删除在 1 中获取的日历槽会怎样?
DB会抛出外键违规异常
如果在步骤 2 之后但在步骤 3 之前预订了另一个预约怎么办?
DB会抛出重复键异常
接下来您需要做的是捕获这两个异常并将用户重定向回预订页面。再次从数据库重新加载数据并检查是否有无效条目,通知用户进行修改并重试。
对于死锁部分,它实际上取决于您的表结构。访问数据的方式、索引数据的方式以及数据库的查询计划。对此没有明确的答案。
| 归档时间: |
|
| 查看次数: |
284 次 |
| 最近记录: |