输入状态在直接读取和从变量读取时显示不同的值

时间:2011-09-21 14:45:48

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

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

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

在上面的代码中,你可以看到,当i entry.State说它没有改变时,如果我db.Entry(person).State它的说法发生了变化。任何人都可以解释为什么??

2 个答案:

答案 0 :(得分:2)

如果您启用了自动更改检测(这是EF 4.1中的默认设置),Entry会在内部调用DetectChanges。该方法可能与此类似:

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

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

此外,您在更改之前创建的State对象的entry将转到Modified,因为DbEntityEntry.State可能是仅传播State的属性内部_internalEntityEntry的值在DbEntityEntry个对象中保持相同的实例。

如果您确实要保存实体的原状态,则需要保存State本身,而不仅仅是entry对象:

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

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

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

db.Configuration.AutoDetectChangesEnabled = false;

在这种情况下,sb.Append...行都将收到状态Unchanged,因为EF现在不再注意到您的某个POCO属性已更改,因为未调用DetectChanges。< / p>

答案 1 :(得分:1)

我认为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;