删除EF实体的所有收集项的正确方法是什么?在下面的代码中,DocumentItems是文档的相关文档项的集合。此代码在Clear()上进行,但在SaveChanges()上失败,因为相关项通过FK连接到其文档,FK是必需的。所以我猜他们在Clear()之后没有外键的情况下仍然悬浮在空中。
我是否通过在每个项目上调用Remove()的集合上的foreach循环来解决这个问题,还是有另一种方法?
// remove existing document items to prepare for refreshing them
existing.DocumentItems.Clear();
// adds new Document Items
PrepareInvoice(existing, collection);
_repository.SaveChanges();
答案 0 :(得分:13)
这是删除集合中项目的一种方法。
VB
TEntityCollection.ToList().ForEach(Sub(o) ctx.DeleteObject(o))
C#
TEntityCollection.ToList().ForEach(x => ctx.DeleteObject(x))
然后你需要打电话
ctx.SaveChanges()
答案 1 :(得分:11)
Clear只删除引用,但不删除entiy。
在你的情况下
existing.DocumentItems.Clear();
EntitySet中的所有DocumentItem都将被清除,但您必须删除/删除实际的DocumentItem或提交失败,就像您尝试在数据库中删除它一样。
你需要循环遍历任何引用,然后删除你想删除的实体(除非它可以为空,在你的情况下它不是)
或者,我已经看到使用clear的实现,以及一个AssociationChangedHandler来自动删除旧对象。基本上,如果更改是“删除/删除”,则会在孤立对象上调用DeleteObject()。
答案 2 :(得分:2)
技巧:在设置父级和子级之间的关系时,您必须在子级上创建“复合”键。这样,当您告诉Parent删除其1个或所有子节点时,实际上将从数据库中删除相关记录。
使用Fluent API配置组合键:
modelBuilder.Entity<Child>.HasKey(t => new { t.ParentId, t.ChildId });
然后,删除相关的孩子:
var parent = _context.Parents.SingleOrDefault(p => p.ParentId == parentId);
var childToRemove = parent.Children.First(); // Change the logic
parent.Children.Remove(childToRemove);
// or, you can delete all children
// parent.Children.Clear();
_context.SaveChanges();
完成!
答案 3 :(得分:1)
是的,一岁,但是一点点注意......因为DeleteObject接受一个参数,它与lambda表达式的参数类型相同,所以你可以使用:
entityCollection.ToList().ForEach(ctx.DeleteObject);
我不确定VB是否支持类似的语法。任何人吗?
答案 4 :(得分:0)
回答Nix对答案的评论,
在我看来,EntityCollection.Remove方法只标记删除关系而不是实体,就像EntityCollection.Clear方法一样。
我知道文档说该实体也会被标记为删除,但在我的测试中我得到了我描述的行为(任何人都可以解释我为什么?)。
因此,如果概念模型中有一对多的外键约束,则无法将更改保存到持久性存储中的上下文中。
我找到的唯一方法(因为我不想CascadeDelete)循环遍历子节点并在每个子节点上调用context.DeleteObject,从而删除实体和关联的关系。