net mvc migrations framework first español code c# entity-framework code-first

c# - mvc - entity framework model first



¿Cómo eliminar el niño uno a muchos registros relacionados en la primera base de datos del código EF? (4)

Bueno, tengo un modelo relacionado de uno a muchos:

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

Lo que quiero hacer es borrar Parent.Children y eliminar las entidades secundarias relacionadas de la base de datos. Ya lo intenté:

Clase de contexto de base de datos:

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

esto funciona bien, pero todavía tengo registros redundantes en la base de datos con Parent_Id = null campos Parent_Id = null cuando lo hago

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

en mi clase de repositorio. También el mismo comportamiento es cuando lo hago:

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

con propiedad adicional para Parent en Child clase Child

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

o cuando lo hago

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

con propiedad Parent_Id adicional en Child clase Child

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

Entonces, ¿cómo puedo configurar la eliminación de cascada correctamente? ¿O cómo debería suponer eliminar esas entidades secundarias? Supongo que es una tarea casual, pero me falta algo.


En EF6 una forma más rápida de hacer la operación es ...

context.Children.RemoveRange(parent.Children)


Intenta cambiar a

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

porque virtual es necesario para obtener la carga diferida. como se explica here

Creo que tu padre.Children.clear no está funcionando porque los niños no se han cargado


La eliminación en cascada no tiene ningún efecto aquí porque no elimina el elemento parent simplemente llama a InsertOrUpdate . El procedimiento correcto es eliminar a los niños uno por uno, como por ejemplo:

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


Si su objeto se autorreferencia, puede eliminar hijos de muchos a muchos y de uno a muchos utilizando el siguiente método. Solo recuerde llamar a db.SaveChanges () después :)

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