乐观锁定是否足以确保资金转移等操作的安全?

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.