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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16654828/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 01:34:55  来源:igfitidea点击:

How to remove child one to many related records in EF code first database?

c#entity-frameworkcode-first

提问by Dmytro

Well, I have one-to-many related model:

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

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; }
}

What I want to do is clear Parent.Childrenand remove related child entities from database. I've already tried:

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

Database context class:

数据库上下文类:

modelBuilder.Entity<Parent>()
            .HasMany(p => p.Children)
            .WithOptional()
            .WillCascadeOnDelete(true);

this works fine, but I still have redundant records in database with Parent_Id = nullfields when I do

这工作正常,但是Parent_Id = null当我这样做时,我在带有字段的数据库中仍然有冗余记录

parent.Children.Clear();
repository.InsertOrUpdate(parent);

in my repository class. Also the same behavior is when I do:

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

modelBuilder.Entity<Parent>()
            .HasMany(pr => pr.Children)
            .WithOptional(ri => ri.Parent)
            .WillCascadeOnDelete(true);

with additional Parentproperty in Childclass

ParentChild课堂上有额外的财产

public class Child
{
    ...
    public Parent Parent { get; set; }
    ...
}

or when I do

或者当我做

modelBuilder.Entity<Child>()
            .HasOptional(p => p.Parent)
            .WithMany(p => p.Children)
            .HasForeignKey(p => p.Parent_Id)
            .WillCascadeOnDelete(true);

with additional Parent_Id property in Childclass

Child课堂上有额外的 Parent_Id 属性

public class Child
{
     ...
     public int Parent_Id { get; set; }
     ...
}

So, how can I configure cascade deleting correctly? Or how should I supposed to remove those child entities? I assume this is casual task but I'm just missing something.

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

采纳答案by Slauma

Cascading delete has no effect here because you don't delete the parentbut just call InsertOrUpdate. The correct procedure is to delete the children one-by-one, like so for example:

级联删除在这里不起作用,因为您不删除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();
}

回答by Kirsten Greed

Try changing to

尝试更改为

 public virtual ICollection<Child> Children { get; set; }

because virtual is needed to get lazy loading. as explained here

因为需要 virtual 才能获得延迟加载。为解释 在这里

I think your parent.Children.clear isnt working because the Children have not been loaded

我认为您的 parent.Children.clear 不起作用,因为 Children 尚未加载

回答by Sam Sippe

In EF6 a faster way to do the operation is...

在 EF6 中,一种更快的操作方法是......

 context.Children.RemoveRange(parent.Children)

回答by Matthew Hudson

If your object is self-referencing, you can delete both many-to-many and one-to-many children using the method below. Just remember to call db.SaveChanges() afterwards :)

如果您的对象是自引用的,您可以使用以下方法删除多对多和一对多子项。请记住之后调用 db.SaveChanges() :)

[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
    Object obj = this.db.Objects.Find(id);
    this.DeleteObjectAndChildren(obj);
    this.db.Objects.Remove(obj);
    this.db.SaveChanges();
    return this.Json(new { success = true });
}

/// <summary>
/// This deletes an object and all children, but does not commit changes to the db.
///  - MH @ 2016/08/15 14:42
/// </summary>
/// <param name="parent">
/// The object.
/// </param>
private void DeleteObjectAndChildren(Object parent)
{
    // Deletes One-to-Many Children
    if (parent.Things != null && parent.Things.Count > 0)
    {
        this.db.Things.RemoveRange(parent.Things);
    }

    // Deletes Self Referenced Children
    if (parent.Children != null && parent.Children.Count > 0)
    {
        foreach (var child in parent.Children)
        {
            this.DeleteObjectAndChildren(child);
        }

        this.db.Objects.RemoveRange(parent.Children);
    }
}

回答by Konrad

This is called "deleting orphans".

这称为“删除孤儿”。

Can EF automatically delete data that is orphaned, where the parent is not deleted?

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

I don't know how it works in EF6 but in EF Core it works fine https://docs.microsoft.com/en-us/ef/core/saving/cascade-deleteso you don't necessarily need to delete the parent for cascades to work.

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

Delete orphans examples

删除孤儿示例