如何在实体框架中完全锁定行

本文关键字:锁定 框架 实体 | 更新日期: 2023-09-27 18:30:46

我正在处理我们正在处理货币交易的情况。

例如,我有一个用户钱包表,他们的余额在该行中。

UserId; Wallet Id; Balance

现在,在我们的网站和网络服务中,每次发生某项交易时,我们都需要:

  1. 检查是否有足够的资金可用于执行该交易:
  2. 从余额中扣除交易成本。

在整个交易期间锁定该行/实体的正确方法是什么?

从我所读到的内容来看,有一些解决方案,其中 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)

可重复读取总结:对查询中使用的所有数据都放置了锁,以防止其他用户更新数据。防止不可重复的读取,但仍有可能出现幻像行。

事务数据库的全部意义在于,数据的使用者决定了他们的数据视图应该有多隔离。

无论您的事务是否序列化,其他人都可以对您刚刚更改但未提交的相同数据执行脏读取。

您应该首先关注视图的完整性,然后只接受该视图质量的降级,以便在您确定需要的情况下提高系统性能。

所有东西都包裹在具有隔离级别的TransactionScopeSerialized您个人不会真正出错。仅当您看到确实需要隔离级别时,才降低隔离级别(即有时出错时还可以)。

有人在这里问这个问题:SQL Server:防止存储过程中的脏读