繁体   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