在我的School EF Model
中,我与Kids
和Tutorials
建立了多对多的关系。
让我们假设孩子和教程中都有现有项目,现在我们只想改变他们现有的关系。也就是说,添加/删除一些孩子的教程。
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!
我的代码出了什么问题?如何让它更新多对多关系?
答案 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),然后使用结果更新多对多关系,但不使用内存中的对象。