如何在实体框架中完全锁定行
本文关键字:锁定 框架 实体 | 更新日期: 2023-09-27 18:30:46
我正在处理我们正在处理货币交易的情况。
例如,我有一个用户钱包表,他们的余额在该行中。
UserId; Wallet Id; Balance
现在,在我们的网站和网络服务中,每次发生某项交易时,我们都需要:
- 检查是否有足够的资金可用于执行该交易:
- 从余额中扣除交易成本。
在整个交易期间锁定该行/实体的正确方法是什么?
从我所读到的内容来看,有一些解决方案,其中 EF 标记一个实体,然后在将其保存回数据库时比较该标记,但是当其他用户/程序已经编辑了数量时它会做什么?
我可以使用 EF 实现此目的吗?如果没有,我还有什么其他选择?
调用存储过程是否可能允许我正确锁定该行,以便在程序 A 锁定该行时,其他人无法访问 SQL Server 中的该行?
EF 没有内置的锁定机制,您可能需要使用原始查询,例如
using (var scope = new TransactionScope(...))
{
using (var context = new YourContext(...))
{
var wallet =
context.ExecuteStoreQuery<UserWallet>("SELECT UserId, WalletId, Balance FROM UserWallets WITH (UPDLOCK) WHERE ...");
// your logic
scope.Complete();
}
}
您可以在实体框架中设置事务的隔离级别,以确保没有其他人可以更改它:
YourDataContext.Database.BeginTransaction(IsolationLevel.RepeatableRead)
可重复读取总结:对查询中使用的所有数据都放置了锁,以防止其他用户更新数据。防止不可重复的读取,但仍有可能出现幻像行。
事务数据库的全部意义在于,数据的使用者决定了他们的数据视图应该有多隔离。
无论您的事务是否序列化,其他人都可以对您刚刚更改但未提交的相同数据执行脏读取。
您应该首先关注视图的完整性,然后只接受该视图质量的降级,以便在您确定需要的情况下提高系统性能。
将所有东西都包裹在具有隔离级别的TransactionScope
中Serialized
您个人不会真正出错。仅当您看到确实需要隔离级别时,才降低隔离级别(即有时出错时还可以)。
有人在这里问这个问题:SQL Server:防止存储过程中的脏读