我有以下的(伪)代码......实际的代码要复杂得多,但这是根本问题的要点:如何防止实体框架4.x中的孤立对象?
string customXML = GoFetchCustomXML();
using (MyContext ctx = new MyContext(...))
{
SomeTable tbl = CreateEntryInTable(customXML);
ctx.SomeTables.AddObject(tbl);
ctx.SaveChanges();
}
...
public SomeTable CreateEntryInTable(string customXML)
{
XDocument doc = XDocument.Parse(customXML);
SomeTable ret = new SomeTable();
foreach (XElement descendant in doc.Descendants("ChildObject").ToList())
{
ChildTable ct = new ChildTable();
// Set some initial items about ct based on
// customer configurations. It sets our StatusCodeID to "NEW".
initializeCT(ct, SomeGlobalCustomerObject);
if (ValidateChildObject(descendant, ct))
{
// Set final ct properties here. We move the
// StatusCodeID to "Valid" among many other things.
// Before we go on, set CreateDate
ct.CreateDate = DateTime.Now;
ret.ChildTables.AddObject(ct);
} else {
// Do nothing. We've changed our mind about needing
// a ChildTable object.
}
}
return ret;
}
我已经花掉了今天8小时追下来这很奇怪的问题。我遇到了一个谜题:The element at index 0 in the collection of objects to refresh is in the added state. Objects in this state cannot be refreshed.
当我运行代码时,在“后代”的第三个循环中,它没有通过验证,所以它永远不会被添加到ChildTables中。这应该是有效的,对吗? (如果没有,请让我知道!)
然而,正如我深深的发现 - 它已被添加到上下文莫名其妙。它的身份栏实际上是“0”。当程序进入“SaveChanges()”时,它会崩溃,因为记录上的日期(创建日期)是00/00/0001,这在数据库中无效。当我把profiler放在连接上时,我看到它的StatusCodeID == NEW ...但是这个记录从来没有完成过,也没有添加到CTX对象或ChildTables中。
更糟糕的是,现在这是在这个状态,上下文是烤面包。我无法找到该记录来杀死它,并且我无法保存任何内容,因为它是上下文中某处的孤立记录。
如果我跳过“无效”对象或重写我的代码,直到我们确定它将被真正需要并添加到ChildTables时才创建对象,那么它就可以工作。但是我上面所做的应该是合法的,不是吗?如果没有,有人可以解释为什么吗?
我猜'ct'是附加到'initializeCT()'中的上下文。 –
不是。它从未附加到代码中的上下文中。我已经证实了这一点。 – Jerry