与实体框架的并发性&;SQL(ADO.NET)

本文关键字:SQL ADO NET amp 框架 实体 并发 | 更新日期: 2023-09-27 18:27:31

我遇到了一些并发问题。我阅读了中的乐观并发处理http://blogs.msdn.com/b/alexj/archive/2009/05/20/tip-19-how-to-use-optimistic-concurrency-in-the-entity-framework.aspx

我有一段代码可以在我的WCF服务中进行实践测试:

    public GameResult PurchaseGameItem(int itemId)
    {
        using (var entities = new GameEntities())
        {
            var p1 = entities.Items.Where(p => p.ID == itemId).FirstOrDefault();
            p1.Coins = 1;
            using (var e2 = new GameEntities())
            {
                var p2 = e2.Items.Where(p => p.ID == itemId).FirstOrDefault();
                p2.Coins = 2;
                e2.SaveChanges();
            }
            entities.SaveChanges();
        }
        return GameResult.Success;
    }

此外,我已经将模型中的"Coins"并发模式设置为"Fixed"。但是,这会通过,并且保存在数据库中的值为"1"。我尝试过一些值集,所以这并不是说它"偶然正确"。为什么这里没有引发OptimisticConcurrentException?

[update#1]通过尝试下面的第一个响应并将它们组合在一起,我成功地得到了一个DbUpdateConcurrentException。这仍然不是我所期望的OptimisticConcurrentException,但它是有意义的。基本上,我不知道为什么它没有一直发生。

            var p1 = entities.Items.Where(p => p.ID == itemId).FirstOrDefault();
            var p3 = entities.Items.Where(p => p.ID == itemId).FirstOrDefault();
            p1.CoinValue = 14;
            p3.CoinValue = 115;
            using (var e2 = new GameEntities())
            {
                var p2 = e2.Items.Where(p => p.ID == itemId).FirstOrDefault();
                p2.CoinValue = 72;
                e2.SaveChanges();
            }
            entities.SaveChanges(); // This throws DbUpdateConcurrencyException, perhaps 50% of the time.

这里似乎存在并发问题!!:D

[update#2]好吧,我现在想好了其中的一部分,这主要是愚蠢的用户错误。DbUpdateConcurrencyException自第二次以来只抛出一次,第二个子句会将其更新为已存在的值,因此该部分是合乎逻辑的。如果从同一上下文中提取了两个实体,则只需考虑后一个更改,因此在第一个响应所建议的"一个数据库连接"情况下,不会引发并发异常。这是合乎逻辑的,因为程序员可以不通过多个句柄访问对象。

但我没有得到DbUpdateConcurrentException和OptimisticConcurrentException之间的区别。我无法提出后者。

与实体框架的并发性&;SQL(ADO.NET)

OptimisticConcurrentException来自ADO.NET,它是ADO.NET实体框架的基础。DbUpdateConcurrencyException由实体框架生成。如果不通过连接/命令对象直接使用ADO.NET,则在使用实体框架时不应遇到OptimisticConcurrentException。

我很奇怪你为什么创建了两个到数据库的连接?!

public GameResult PurchaseGameItem(int itemId)
{
    using (var entities = new GameEntities())
    {
        var p1 = entities.Items.Where(p => p.ID == itemId).FirstOrDefault();
        var p2 = entities.Items.Where(p => p.ID == itemId).FirstOrDefault();
        p1.Coins = 1;
        p2.Coins = 2;
        entities.SaveChanges();
    }
    return GameResult.Success;
}