簡體   English   中英

如何防止Entity Framework 4.x中的孤立對象?

[英]How do I prevent orphaned objects in Entity Framework 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. 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,這在數據庫中無效。 當我在連接上放置探查器時,我看到它的StatusCodeID == NEW ...但是這條記錄從未完成,並且從未添加到CTX對象或ChildTables。

更糟糕的是,現在這是在這種狀態,上下文是敬酒。 我找不到這條記錄來殺死它,我無法保存任何東西,因為它是在上下文中某處的孤立記錄。

如果我跳過“無效”對象或重寫我的代碼,使得在我們確實需要將對象真正需要並添加到ChildTables之后才創建對象,那么它可以工作。 但我上面所做的應該是合法的,不是嗎? 如果沒有,有人可以解釋原因嗎?

我找到了答案,或者至少是一個非常重要的解決方案。

1)除非我非常確定我需要添加它們,否則不要創建對象。 我可以重新修改ValidateChildObject以使Descendant和SomeCustomerObject確定它是否有效,並且只有在規則通過時才創建和初始化。

2)然而,有些情況在當前設計中這是不可行的,因為它會減慢速度 - 無論我需要做什么來驗證某些設置,我都必須再做一次,以便在initializeCT中設置這些值。 在這些情況下,如上面的“ELSE”條款,我需要做:

...
} 
else 
{
    // Remove it from the ChildTables anyway, just in case 
    // it was magically added. If it was not added, this does not fail.
    ctx.ChildTables.DeleteObject(ct);
}

當我執行這兩種方法之一時,我的代碼運行順利。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM