我有以下的(僞)代碼......實際的代碼要複雜得多,但這是根本問題的要點:如何防止實體框架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