【问题标题】:Entry state showing different values when read directly and when read from a variable直接读取和从变量读取时显示不同值的条目状态
【发布时间】:2011-11-22 01:00:29
【问题描述】:

我在 asp.net mvc 中使用实体框架 4.1 和代码。只是为了测试学习我写了下面的代码(一个控制器)。

public ActionResult Foo()
{
     StringBuilder sb = new StringBuilder();
            using (var db = new DemoDataBase1Context())
            {
                //get person from db
                var person = db.Persons.FirstOrDefault();

                //get entry
                var entry = db.Entry(person);

                //now change the person object
                person.Name = "Some New Value";  

               //print entity state

                //this is showing unchanged
                sb.Append("<br>State: " + entry.State);  

                //this is showing changed
                sb.Append("<br>State: " + db.Entry(person).State);                 
            }

     return Content(sb.ToString());
}

在上面的代码中你可以看到,当我做entry.State 时它的说法不变,如果我做db.Entry(person).State 它的说法改变了。谁能解释一下原因??

【问题讨论】:

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


    【解决方案1】:

    如果您启用了自动更改检测(这是 EF 4.1 中的默认设置)Entry 在内部调用 DetectChanges。方法开始大概是这样的:

    if (Configuration.AutoDetectChangesEnabled)
        ChangeTracker.DetectChanges();
    //...
    

    在您第二次调用db.Entry(person) 时,对象已更改,DetectChanges 方法通过将加载实体时生成的快照与当前值进行比较来检测到这一点。由于存在差异,因此状态从 Unchanged 更改为 Modified

    此外,您在更改之前创建的entry 对象的State 将转到Modified,因为DbEntityEntry.State 很可能只是传播内部_internalEntityEntryState 值的属性,该值仍然存在两个 DbEntityEntry 对象中的相同实例。

    如果你真的想保存实体的先前状态,你需要保存 State 本身,而不仅仅是 entry 对象:

    var state = db.Entry(person).State;
    

    这只是一个枚举,以后调用 Entry 时不会改变。

    您可以将此行为与禁用自动更改检测时的行为进行比较:

    db.Configuration.AutoDetectChangesEnabled = false;
    

    在这种情况下,两条 sb.Append... 行都将收到状态 Unchanged,因为 EF 现在不再注意到您的 POCO 属性之一已更改,因为未调用 DetectChanges

    【讨论】:

      【解决方案2】:

      我认为 Entry 方法可以为您提供调用 Entry 时对象的状态。我认为这与从变量中读取它与直接调用它没有任何关系。

      当您获得对第一个条目的引用时,您的对象不会更改。下一行您更改它并再次调用 Entry,此时它已更改。如果您存储对它的引用,然后比较两者,我猜它们是不同的引用:

      var person = db.Persons.FirstOrDefault();
      
      // get reference to entry - unchanged at this point
      var entry1 = db.Entry(person);
      
      // make a change to the object
      person.Name = "Changed";
      
      // get reference to entry - changed now
      var entry2 = db.Entry(person);
      
      // these will not be equal: probably false
      var equalOrNot = entry1 == entry2;
      

      【讨论】:

      • 我刚刚检查过:在此声明之后var entry2 = db.Entry(person); | entry1.Stateentry2.State,现在都说修改了。现在我刚刚注释掉了var entry2 = db.Entry(person);entry1.State 显示已修改。我不知道为什么会这样。
      • 更新您的代码以显示您在做什么。当我运行测试时,它按预期工作。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-12-15
      • 1970-01-01
      • 2019-02-08
      • 2017-06-09
      • 2019-09-21
      • 2012-01-14
      • 1970-01-01
      相关资源
      最近更新 更多