乐观锁定是否足以确保资金转移等操作的安全?
Is optimistic locking enough to secure operations such as funds transfer?
在下面的示例中,我们可能会 运行 出现并发错误,如果发送方决定同时向 2 个不同的接收方发送资金,那么两个接收方都可能收到钱,而发送方只会被收取费用一次。
public async Task SendMoney(int amount, int sender, int receiver)
{
await using var dbContext = new ApplicationDbContext();
var person1 = await dbContext.Persons.FirstOrDefaultAsync(p => p.Id == sender);
var person2 = await dbContext.Persons.FirstOrDefaultAsync(p => p.Id == receiver);
if (person1.Balance >= amount)
{
person1.Balance -= amount;
person2.Balance += amount;
}
await dbContext.SaveChangesAsync();
}
避免这种情况并确保此操作安全的最佳方法是什么?
通过向 Person
模型添加时间戳 属性 [Timestamp] public byte[] Version { get; set; }
来引入乐观锁定是否足以确保无法重复资金?
我最关心避免重复的安全性。正确处理 DbUpdateConcurrencyException
等异常以提供流畅的用户体验不在我的问题范围内。
在并发环境中 [Timestamp]
将确保只有在从数据库加载后未更改的行才会被保存,因此它会起作用。
同样对于您提供的案例,可以将 Balance
字段设置为 Concurrency Token.
在下面的示例中,我们可能会 运行 出现并发错误,如果发送方决定同时向 2 个不同的接收方发送资金,那么两个接收方都可能收到钱,而发送方只会被收取费用一次。
public async Task SendMoney(int amount, int sender, int receiver)
{
await using var dbContext = new ApplicationDbContext();
var person1 = await dbContext.Persons.FirstOrDefaultAsync(p => p.Id == sender);
var person2 = await dbContext.Persons.FirstOrDefaultAsync(p => p.Id == receiver);
if (person1.Balance >= amount)
{
person1.Balance -= amount;
person2.Balance += amount;
}
await dbContext.SaveChangesAsync();
}
避免这种情况并确保此操作安全的最佳方法是什么?
通过向 Person
模型添加时间戳 属性 [Timestamp] public byte[] Version { get; set; }
来引入乐观锁定是否足以确保无法重复资金?
我最关心避免重复的安全性。正确处理 DbUpdateConcurrencyException
等异常以提供流畅的用户体验不在我的问题范围内。
在并发环境中 [Timestamp]
将确保只有在从数据库加载后未更改的行才会被保存,因此它会起作用。
同样对于您提供的案例,可以将 Balance
字段设置为 Concurrency Token.