实体框架正确地更新多对多关系

时间:2016-05-26 05:58:40

标签: c# entity-framework

在我的School EF Model中,我与KidsTutorials建立了多对多的关系。 让我们假设孩子和教程中都有现有项目,现在我们只想改变他们现有的关系。也就是说,添加/删除一些孩子的教程。

var kid; //the request target to modify relationships
//kid.Tutorials has the old existing relationships to be modified by add/del
var tutorialsToAdd; //the request to add relationships
var tutorialsToDel; //the request to del relationships
using (var conn = new SchoolEFModels(efConnectionStr)) {
    conn.Kids.Attach(kid);
    kid.Tutorials.ForEach(t => conn.Tutorials.Attach(t));
    kid.Tutorials.AddRange(tutorialsToAdd); //simple add extension in batch
    kid.Tutorials.RemoveRange(tutorialsToDel); //simple del extension in batch
    conn.SaveChanges();
}

当我这样做时,我得到一个例外:

"Cannot insert duplicate key in object 'dbo.Tutorials'. The duplicate key value is (10)."

我可以看到EF正在尝试创建新的教程项目,而不是为我更新现有的关系。这是我不想要的。你误解了EF!

我的代码出了什么问题?如何让它更新多对多关系?

1 个答案:

答案 0 :(得分:0)

我明白了。

添加/删除它会使EntityState变为已添加/已删除。因此,如文章所述,让它重新插入现有的ID,谢谢Gert那里的链接。

因此,如果您将每个conn.entry(kid/tutorials).State修改为EntityState.Modified,然后调用conn.ChangeTracker.DetectChanges();,然后调用conn.SaveChanges();,它将只按预期更新多对多表。

更新:

你需要小心一件事。如果“孩子和教程”的内存中对象列表彼此链接。例如Kids[0].Tutorials[0] == Tutorials[0] && Tutorial[0].Kids[0] == Kids[0] EF将无法为您处理此死循环。您需要先打破此循环链接。 为此,我的方法是打开一个Connection并阅读Kid out Includes(Tutorials),然后使用结果更新多对多关系,但不使用内存中的对象。