Eh bien, j'ai un modèle associé un à plusieurs:
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; }
}
Ce que je veux faire est clair Parent.Children
et supprimez les entités enfant associées de la base de données. J'ai déjà essayé:
Classe de contexte de base de données:
modelBuilder.Entity<Parent>()
.HasMany(p => p.Children)
.WithOptional()
.WillCascadeOnDelete(true);
cela fonctionne bien, mais j'ai toujours des enregistrements redondants dans la base de données avec Parent_Id = null
champs quand je le fais
parent.Children.Clear();
repository.InsertOrUpdate(parent);
dans ma classe de référentiel. Aussi le même comportement est quand je fais:
modelBuilder.Entity<Parent>()
.HasMany(pr => pr.Children)
.WithOptional(ri => ri.Parent)
.WillCascadeOnDelete(true);
avec une propriété supplémentaire Parent
dans Child
class
public class Child
{
...
public Parent Parent { get; set; }
...
}
ou quand je fais
modelBuilder.Entity<Child>()
.HasOptional(p => p.Parent)
.WithMany(p => p.Children)
.HasForeignKey(p => p.Parent_Id)
.WillCascadeOnDelete(true);
avec une propriété additionnelle Parent_Id dans la classe Child
public class Child
{
...
public int Parent_Id { get; set; }
...
}
Alors, comment puis-je configurer la suppression en cascade correctement? Ou comment devrais-je supposer supprimer ces entités enfants? Je suppose que c'est une tâche occasionnelle, mais que quelque chose me manque.
La suppression en cascade n'a aucun effet ici car vous ne supprimez pas le parent
, mais vous appelez simplement InsertOrUpdate
. La procédure correcte consiste à supprimer les enfants un par un, comme par exemple:
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();
}
En EF6, un moyen plus rapide d'opérer est ...
context.Children.RemoveRange(parent.Children)
Cela s'appelle "supprimer des orphelins".
EF peut-il supprimer automatiquement les données orphelines où le parent n'est pas supprimé?
Je ne sais pas comment cela fonctionne dans EF6, mais dans EF Core, cela fonctionne très bien https://docs.Microsoft.com/en-us/ef/core/saving/cascade-delete Il n'est pas nécessaire de supprimer le parent pour que cascades fonctionne.
Essayez de changer pour
public virtual ICollection<Child> Children { get; set; }
car virtuel est nécessaire pour obtenir un chargement paresseux. comme expliqué ici
Je pense que votre parent.Children.clear ne fonctionne pas parce que les enfants n'ont pas été chargés
Si votre objet fait référence à vous-même, vous pouvez supprimer les enfants plusieurs-à-plusieurs et un-à-plusieurs en utilisant la méthode ci-dessous. Rappelez-vous simplement d'appeler db.SaveChanges () aprè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);
}
}