我遇到了一个有趣的问题,实体框架并基于我必须用来解决它的代码,我怀疑我的解决方案不太理想。我在表A和表B之间具有1对多的关系,其中表B中的实体具有对TableA的引用。我有一个场景,我想同时删除TableA中连续的所有子项,我认为这可以通过简单地清除集合来实现:
Entity.Children.Clear()
不幸的是,当我尝试保存更改时,这会产生外键违规。
正在添加关系或 从AssociationSet中删除 'FK_EntityB_EntityA'。有基数 约束,相应的'EntityB' 也必须添加或删除。
我提出的解决方案是通过实体上下文的DeleteObject()手动删除对象,但我只知道我使用的这个逻辑必定是错误的。
while (collection.Any())
Entities.DeleteObject(collection.First());
首先,我必须使用Where()循环的事实似乎远远不够理想,但我认为这纯粹是我的语义评估。在任何情况下,我是如何做到这一点的,或者是否有更好的方法来清除实体的子实体集合,以便实体框架在所有被删除的对象上正确调用数据存储删除?
答案 0 :(得分:20)
Clear()
将引用移除到实体,而不是实体本身。
如果您打算始终执行相同的操作,则可以处理AssociationChanged
:
Entity.Children.AssociationChanged +=
new CollectionChangeEventHandler(EntityChildrenChanged);
Entity.Children.Clear();
private void EntityChildrenChanged(object sender,
CollectionChangeEventArgs e)
{
// Check for a related reference being removed.
if (e.Action == CollectionChangeAction.Remove)
{
Context.DeleteObject(e.Element);
}
}
您可以使用部分类将其构建到您的实体中。
答案 1 :(得分:6)
您可以创建父实体和子实体之间的标识关系,当您从父集合中删除子实体时,EF将删除子实体。
public class Parent
{
public int ParentId {get;set;}
public ICollection<Child> Children {get;set;}
}
public class Child
{
public int ChildId {get;set;}
public int ParentId {get;set;}
}
映射配置:
modelBuilder.Entity<Child>().HasKey(x => new { x.ChildId, x.ParentId });
modelBuilder.Entity<Parent>().HasMany(x => x.Children).WithRequired().HasForeignKey(x => x.ParentId);
答案 2 :(得分:5)
技巧:在设置父级和子级之间的关系时,您必须在子级上创建“复合”键。这样,当您告诉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);
// you can delete all children if you want
// parent.Children.Clear();
_context.SaveChanges();
完成!