【问题标题】:Entity Framework Optimistic Concurrency Exception not occuring实体框架乐观并发异常未发生
【发布时间】:2011-03-16 15:32:32
【问题描述】:

我们有一个使用 EF4 作为其数据访问层的 ASP.Net MVC 应用程序,我们看到了与 OptimisitcConcurrencyExceptions 相关的意外行为,而我们认为它们应该不会被抛出。

我们已将问题简化为以下代码...

   using System.Linq;
    using Project.Model;

    namespace OptimisticConcurrency
    {
        class Program
        {
            static void Main()
            {
                Contact firstContact = null;
                using (var firstEntities = new ProjectEntities())
                {
                    firstContact = (from c in firstEntities.Contacts 
                       where c.LastName == "smith" select c).Single();
                }

                using (var secondEntities = new ProjectEntities())
                {
                    var secondContact = (from c in secondEntities.Contacts 
                       where c.LastName == "smith" select c).Single();

                    secondContact.Title = "a";
                    secondEntities.SaveChanges();
                }

                firstContact.Title = "b";

                using (var thirdEntities = new ProjectEntities())
                {
                    var thirdContact = (from c in thirdEntities.Contacts 
                       where c.LastName == "smith" select c).Single();

                    thirdContact.Title = firstContact.Title;

                    //EXPLICITLY SET VERSION HERE
                    thirdContact.Version = firstContact.Version;  

                    thirdEntities.SaveChanges();
                }
            }
        }
    }

这是在我们的 MVC 应用程序中发生的一个相当简单的版本,但是会出现同样的问题。

当我们在第三个实体上调用 SaveChanges 时,我预计会出现异常并且没有抛出任何东西。

更有趣的是,当我们附加 SQL Profiler 时,我们看到在 where 子句中使用了 Version,但使用的是 thirdEntities Version 值(数据库中的当前值),而不是 firstEntities 值,尽管它是在调用 SaveChanges 之前显式设置。 SaveChanges 正在将 Version 重置为检索到的值而不是设置值。

在 EDMX 中,版本设置为将 StoreGeneratedPattern 设置为 Computed。

有人知道这里发生了什么吗?

【问题讨论】:

    标签: asp.net-mvc-3 entity-framework-4 optimistic-concurrency


    【解决方案1】:

    这是个问题。一旦该列设置为Computed,您就不能在应用程序中设置它的值(可以但不使用该值)。

    编辑:

    如果您从数据库加载实体,则默认情况下会使用上下文进行跟踪。上下文存储其原始值。例如,原始值用于快照更改跟踪,但它们也用作Computed 属性的唯一有效来源。如果您在实体中设置 Computed 属性,则不使用该值,而是使用原始值。解决方法是修改原始值(在您修改其他任何内容之前):

    using (var context = new TestEntities())
    {
        var entityToUpdate = context.MyEntities.Single(e => e.Id == someId);
        entityToUpdate.Timestamp = entity.Timestamp;
    
        ObjectStateEntry entry = context.ObjectStateManager.GetObjectStateEntry(entityToUpdate);
        entry.ApplyOriginalValues(entityToUpdate);
    
        // set modified properties
        context.SaveChanges();
    }
    

    编辑 2:

    顺便说一句。一旦您同时拥有实际加载的时间戳和之前检索的时间戳,您就可以简单地compare them in your application 而不是在数据库中进行。

    【讨论】:

    • 当我将 Version 列设置为 StoreGeneratedPattern = None 然后我得到一个异常,说我无法更新数据库中的时间戳列。
    • 是的,这种行为完全不起作用。我会在晚上尝试一种解决方法并通知您。
    猜你喜欢
    • 2023-03-03
    • 2015-06-27
    • 1970-01-01
    • 2011-02-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多