我在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
它的说法发生了变化。任何人都可以解释为什么??
答案 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;