如何在EF代码第一个数据库中删除子一对多的相关记录?

Dmy*_*tro 61 c# entity-framework code-first

好吧,我有一对多的相关模型:

public class Parent
{
    public int Id { get; set; }
    public string Name { get; set; }
    public ICollection<Child> Children { get; set; }
}

public class Child
{
    public int Id { get; set; }
    public string ChildName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我想要做的是清除Parent.Children并从数据库中删除相关的子实体.我已经尝试过了:

数据库上下文类:

modelBuilder.Entity<Parent>()
            .HasMany(p => p.Children)
            .WithOptional()
            .WillCascadeOnDelete(true);
Run Code Online (Sandbox Code Playgroud)

这工作得很好,但我还是在数据库冗余记录与Parent_Id = null领域,当我做

parent.Children.Clear();
repository.InsertOrUpdate(parent);
Run Code Online (Sandbox Code Playgroud)

在我的存储库类中.当我这样做时,同样的行为:

modelBuilder.Entity<Parent>()
            .HasMany(pr => pr.Children)
            .WithOptional(ri => ri.Parent)
            .WillCascadeOnDelete(true);
Run Code Online (Sandbox Code Playgroud)

ParentChild课堂上有额外的财产

public class Child
{
    ...
    public Parent Parent { get; set; }
    ...
}
Run Code Online (Sandbox Code Playgroud)

或当我这样做

modelBuilder.Entity<Child>()
            .HasOptional(p => p.Parent)
            .WithMany(p => p.Children)
            .HasForeignKey(p => p.Parent_Id)
            .WillCascadeOnDelete(true);
Run Code Online (Sandbox Code Playgroud)

Child类中添加其他Parent_Id属性

public class Child
{
     ...
     public int Parent_Id { get; set; }
     ...
}
Run Code Online (Sandbox Code Playgroud)

那么,如何正确配置级联删除?或者我应该如何删除这些子实体?我认为这是一项随意的任务,但我只是遗漏了一些东西.

Sam*_*ppe 98

在EF6中,更快的方法是...

 context.Children.RemoveRange(parent.Children)
Run Code Online (Sandbox Code Playgroud)

  • @VCD它比调用context.Children.Remove(child)对每个孩子都快,但没有运行sql"DELETE FROM Children where parentId = @ parentId"快 (2认同)

Sla*_*uma 63

级联删除在此处无效,因为您不删除parent但只是调用InsertOrUpdate.正确的程序是逐个删除子项,例如:

using (var context = new MyContext())
{
    var parent = context.Parents.Include(p => p.Children)
        .SingleOrDefault(p => p.Id == parentId);

    foreach (var child in parent.Children.ToList())
        context.Children.Remove(child);

    context.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)

  • 而不是预先处理所有"子"对象,只需要说"context.Children.RemoveRange(parent.Children.ToArray())",这样每次调用Remove时DbContext都不需要做太多的工作检查.对于删除操作来说,这可能不是一个很大的性能问题,但是当我在for循环中使用`context.Children.Add(child)`测试添加100k记录时,我注意到一次添加一个项目时存在巨大差异. (19认同)
  • @kirsteng:级联删除意味着删除子项**如果**删除父项.但是在这个问题中没有父母被删除.因此,级联删除不适用于此方案. (6认同)

Kon*_*rad 7

这称为“删除孤儿”。

EF 可以自动删除孤立的数据,而父数据没有被删除吗?

我不知道它在 EF6 中是如何工作的,但在 EF Core 中它工作正常https://docs.microsoft.com/en-us/ef/core/saving/cascade-delete所以你不一定需要删除级联工作的父级。

删除孤儿示例