实体框架 - 清除子集合

时间:2010-01-13 17:11:23

标签: entity-framework

我遇到了一个有趣的问题,实体框架并基于我必须用来解决它的代码,我怀疑我的解决方案不太理想。我在表A和表B之间具有1对多的关系,其中表B中的实体具有对TableA的引用。我有一个场景,我想同时删除TableA中连续的所有子项,我认为这可以通过简单地清除集合来实现:

Entity.Children.Clear()

不幸的是,当我尝试保存更改时,这会产生外键违规。

  

正在添加关系或   从AssociationSet中删除   'FK_EntityB_EntityA'。有基数   约束,相应的'EntityB'   也必须添加或删除。

我提出的解决方案是通过实体上下文的DeleteObject()手动删除对象,但我只知道我使用的这个逻辑必定是错误的。

while (collection.Any())
    Entities.DeleteObject(collection.First());

首先,我必须使用Where()循环的事实似乎远远不够理想,但我认为这纯粹是我的语义评估。在任何情况下,我是如何做到这一点的,或者是否有更好的方法来清除实体的子实体集合,以便实体框架在所有被删除的对象上正确调用数据存储删除?

3 个答案:

答案 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();

完成!