1

简而言之,为什么会失败(myChildObject添加到数据库中)。请注意,它适用于 ObjectContext

using (var db = new dbEntities())
{
    var myParentObject = db.parentObjects.First(); // this definitely exists in the db

    // this **should** attach myChildObject to the context, 
    // and therefore add it to the db on .SaveChanges() - it doesn't!
    var myChildObject = new childObject(){
        parentObject = myParentObject
    };

    db.SaveChanges();
}

这篇 MSDN 博客文章

您可以通过将新实体连接到另一个已被跟踪的实体来将新实体添加到上下文中。这可以通过将新实体添加到另一个实体的集合导航属性或通过将另一个实体的引用导航属性设置为指向新实体来实现。

当然,上面的代码应该可以工作,因为myChildObject引用myParentObject是一个被跟踪的对象。EF 应该足够聪明,可以确定它需要添加到childObjects集合中。当我使用 ObjectContext 时它工作得很好,现在我发现我需要重写我的所有代码才能让它与 dbContext 一起工作。

为了让它工作,我必须像这样重写它:

using (var db = new dbEntities())
{
    var myParentObject = db.parentObjects.First(); // this definitely exists in the db

    var myChildObject = new childObject();

    myParentObject.childObjects.Add(myChildObject);

    db.SaveChanges();
}
4

2 回答 2

1

如果您使用 POCO 实体,ObjectContext它确实有效。但不是因为 EF 的更改跟踪与 with 的工作方式不同,DbContext而是因为 EF 4 T4 模板生成的 POCO 实体包含“关系修复”方法。

基本上,该行的属性设置器parentObject = myParentObject不仅是一个对象分配,而且设置器包括对一个方法的调用,该方法最终完全完成了您现在手动执行的操作,即:myParentObject.childObjects.Add(myChildObject). 此时,规则“您可以通过将新实体连接到已被跟踪的另一个实体来将新实体添加到上下文”适用myChildObject并被添加到上下文并插入到数据库中。

对于为这些修复方法生成 POCO 实体的 T4 模板DbContext已被删除,因为它们在其他情况下会造成问题。尤其是当涉及延迟加载时,您的引用分配和myParentObject.childObjects...属性设置器中的自动调用将触发集合上的延迟加载,并在将新子项添加到集合之前childObjects首先加载已经存储的所有内容。myParentObject如果这些是数千个,这是一个巨大的不必要的开销,性能会变得灾难性,并且如果您不知道运行的修复方法,那么性能突然变差的原因(仅仅因为您分配了一个引用属性)不容易检测到场景。

此处此处以及此处此处是有关关系修复方法引起的混乱的示例。

可以修改 T4 模板并再次添加关系修复方法 - 或者如果您使用 Code-First,只需在实体类中手动编写它们 - 以恢复旧行为。但这可能比按照您在上一个代码片段中概述的方式更改现有代码更复杂,并且至少与更改现有代码一样多 - 我当然更喜欢恢复那些麻烦的修复方法。

于 2013-06-07T20:30:47.830 回答
0

@theyetiman 您对博客文本有一点解释错误。

看:

[...]
或通过设置另一个实体的参考导航属性指向新实体。

在这部分博客中说您可以使用新实体设置跟踪对象的引用导航属性。

像这样:

[跟踪实体].NavigationProperty = [新实体];

但你想做:

[新实体].Navigation Property = [跟踪实体];

这不起作用。如果您的 childObject 被跟踪并且 parentObject 没有,您将能够在 childObject 属性中添加 parentObject 设置它,但反之则不然。

于 2013-06-07T16:07:11.467 回答