4

一般来说,我对 EF 和 SQL 相当陌生,所以我可以使用一些帮助来澄清这一点。

假设我有一个表“钱包”(和 EF 代码第一个对象钱包),它有一个 ID 和一个余额。我需要做这样的操作:

if(wallet.balance > 100){
    doOtherChecksThatTake10Seconds();
    wallet.balance -= 50;
    context.SaveChanges();
}

正如你所看到的,它检查一个条件是否有效,然后如果是,它必须首先执行一堆需要很长时间的其他操作(在这个夸张的例子中,我们说 10 秒),然后如果通过它就减去从钱包中取出 50 美元并保存新数据。

问题是,还有其他事情可以随时更改钱包余额(这是一个 Web 应用程序)。如果发生这种情况:

  1. 钱包余额 = 110;
  2. 此操作通过其“if”检查,因为 wallet.balance > 110
  3. 在执行“doOtherChecksThatTake10Seconds()”时,用户从钱包中转出 40 美元
  4. 现在 wallet.balance = 70
  5. “doOtherChecksThatTake10Seconds()”完成,从 wallet.balance 中减去 50,然后使用新数据保存上下文。

在这种情况下,wallet.balance > 100 的检查不再成立,但由于延迟,操作仍然发生。我需要找到一种方法来锁定表并且在整个操作完成之前不释放它,因此在此期间没有任何内容被编辑。最有效的方法是什么?

应该注意的是,我已经尝试将此操作放在 TransactionScope() 中,我不确定这是否会产生预期的效果,但我确实注意到它开始导致大量死锁,而正在运行的数据库操作完全不同.

4

3 回答 3

4

使用 乐观并发 http://msdn.microsoft.com/en-us/data/jj592904

//Object Property:
public byte[] RowVersion { get; set; }
//Object Configuration:
Property(p => p.RowVersion).IsRowVersion().IsConcurrencyToken();

这允许脏读。但是,当您去更新记录时,系统会检查 rowversion 同时没有更改,如果同时有人更改了记录,则会失败。每次记录更改时,DB 都会维护 Rowversion。

开箱即用的 EF 乐观锁定。

于 2013-08-02T03:40:11.283 回答
0

另一种方法是使用一个或多个内部队列并仅由一个线程使用此队列(生产者-消费者模式)。我在预订系统中使用了这种方法,它运行良好且非常简单。

在我的情况下,我有多个动态创建和删除的队列(每个“产品”一个)和多个消费者,其中只有一个消费者可以分配给一个队列。这也允许处理更高的并发性。在拥有数万用户的高并发场景中,您还可以使用单独的服务器和队列(如 msmq)来处理此问题。

在很多用户想要一张音乐会门票的票务系统或购物系统中,当新的“哈利波特”发布但我没有这种情况时,这种方法可能会出现问题。

于 2013-08-02T08:49:37.513 回答
0

您可以使用事务范围。

导入命名空间

using System.Transactions;

并像下面这样使用它:

public string InsertBrand()
        {
            try
            {

                using (TransactionScope transaction = new TransactionScope())
                {

                   //Do your operations here
                    transaction.Complete();
                    return "Mobile Brand Added";

                }
            }
            catch (Exception ex)
            {

                throw ex;
            }
        }
于 2013-08-02T04:01:43.757 回答