实体框架 - 清除子集合

Nat*_*lor 26 entity-framework

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

Entity.Children.Clear()
Run Code Online (Sandbox Code Playgroud)

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

正在从AssociationSet'FK_EntityB_EntityA'添加或删除关系.对于基数约束,还必须添加或删除相应的"EntityB".

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

while (collection.Any())
    Entities.DeleteObject(collection.First());
Run Code Online (Sandbox Code Playgroud)

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

Cra*_*ntz 21

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);
        }
    }
Run Code Online (Sandbox Code Playgroud)

您可以使用分部类将其构建到您的实体中.


syn*_*ned 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;}
    }
Run Code Online (Sandbox Code Playgroud)

映射配置:

    modelBuilder.Entity<Child>().HasKey(x => new { x.ChildId, x.ParentId });
    modelBuilder.Entity<Parent>().HasMany(x => x.Children).WithRequired().HasForeignKey(x => x.ParentId);
Run Code Online (Sandbox Code Playgroud)


Mos*_*osh 5

技巧:在设置父和子之间的关系时,你必须在孩子身上创建一个"复合"键.这样,当您告诉Parent删除其1个或所有子节点时,实际上将从数据库中删除相关记录.

要使用Fluent API配置组合键:

modelBuilder.Entity<Child>().HasKey(t => new { t.ParentId, t.ChildId });
Run Code Online (Sandbox Code Playgroud)

然后,删除相关的孩子:

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();
Run Code Online (Sandbox Code Playgroud)

完成!