How to totally lock a row in Entity Framework

大城市里の小女人 提交于 2019-12-04 17:24:35

问题


I am working with a situation where we are dealing with money transactions.

For example, I have a table of users wallets, with their balance in that row.

UserId; Wallet Id; Balance

Now in our website and web services, every time a certain transaction happens, we need to:

  1. check that there is enough funds available to perform that transaction:
  2. deduct the costs of the transaction from the balance.

How and what is the correct way to go about locking that row / entity for the entire duration of my transaction?

From what I have read there are some solutions where EF marks an entity and then compares that mark when it saves it back to the DB, however what does it do when another user / program has already edited the amount?

Can I achieve this with EF? If not what other options do I have?

Would calling a stored procedure possibly allow for me to lock the row properly so that no one else can access that row in the SQL Server whilst program A has the lock on it?


回答1:


EF doesn't have built-in locking mechanism, you probably would need to use raw query like

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();
    }
}



回答2:


you can set the isolationlevel on the transaction in Entity framework to ensure no one else can change it:

YourDataContext.Database.BeginTransaction(IsolationLevel.RepeatableRead)

RepeatableRead Summary: Locks are placed on all data that is used in a query, preventing other users from updating the data. Prevents non-repeatable reads but phantom rows are still possible.




回答3:


The whole point of a transactional database is that the consumer of the data determines how isolated their view of the data should be.

Irrespective of whether your transaction is serialized someone else can perform a dirty read on the same data that you just changed, but did not commit.

You should firstly concern yourself with the integrity of your view and then only accept a degredation of the quality of that view to improve system performance where you are sure it is required.

Wrap everthing in a TransactionScope with Serialized isolation level and you personally cannot really go wrong. Only drop the isolation level when you see it is genuinely required (i.e. when getting things wrong sometimes is OK).

Someone asks about this here: SQL Server: preventing dirty reads in a stored procedure



来源:https://stackoverflow.com/questions/27002474/how-to-totally-lock-a-row-in-entity-framework

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!