Подтвердить что ты не робот

Как удалить дочерние одно во многие связанные записи в первой базе данных EF-кода?

Ну, у меня есть одна-ко-многим связанная модель:

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

Что я хочу сделать, это очистить Parent.Children и удалить связанные дочерние сущности из базы данных. Я уже пробовал:

Класс контекста базы данных:

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

это отлично работает, но у меня все еще есть избыточные записи в базе данных с полями Parent_Id = null, когда я делаю

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

в моем классе репозитория. То же самое происходит и в том, что я делаю:

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

с дополнительным свойством Parent в Child классе

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

или когда я делаю

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

с дополнительным свойством Parent_Id в классе Child

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

Итак, как я могу правильно настроить каскадное удаление? Или как я должен удалить эти дочерние объекты? Я предполагаю, что это случайная задача, но я просто что-то пропустил.

4b9b3361

Ответ 1

Каскадное удаление здесь не действует, потому что вы не удаляете 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();
}

Ответ 2

В EF6 более быстрый способ выполнить операцию...

 context.Children.RemoveRange(parent.Children)

Ответ 3

Попробуйте перейти на

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

потому что виртуальный нужен для ленивой загрузки. как объяснено здесь

Я думаю, что ваш parent.Children.clear не работает, потому что дети не загружены

Ответ 4

Если ваш объект является саморегуляцией, вы можете удалить как "много-ко-многим", так и "один ко многим", используя приведенный ниже метод. Просто не забудьте затем вызвать 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);
    }
}