web-dev-qa-db-fra.com

Suppressions en cascade avec Entity Framework - Entités associées supprimées par EF

J'ai un problème avec la suppression dans Entity Framework. En bref, EF essaie explicitement de supprimer une entité de la base de données même si j'ai explicitement configuré EF pour utiliser les suppressions en cascade dans la base de données.

Ma conception:

J'ai trois types d'entités, MainEntity, EntityTypeA et EntityTypeB. EF a été configuré pour utiliser la suppression en cascade lors de la suppression de EntityTypeA et EntityTypeB. En d'autres termes, si je supprime une instance de MainEntity, je souhaite que toutes les instances EntityTypeA et EntityTypeB associées soient également supprimées. Je ne supprime jamais EntityTypeA ou EntityTypeB sans supprimer également leur parent.

Mon problème est que EF émet explicitement une instruction DELETE pour EntityTypeA, ce qui provoque le blocage de mon application.

Voici à quoi ressemble mon modèle:

Les relations ont la configuration non par défaut suivante:

  • MainEntity -> EntityTypeA OnDelete: Cascade
  • MainEntity -> EntityTypeB OnDelete: Cascade

La relation EntityTypeA -> EntityTypeB a OnDelete: None

Contenu de la base de données

INSERT INTO MainEntities (Name) values ('Test')
insert into EntityTypeA (MainEntityID) VALUES (1)
insert into EntityTypeB (MainEntityID, EntityTypeAId) VALUES (1, 1)
insert into EntityTypeB (MainEntityID, EntityTypeAId) VALUES (1, 1)

Mon code:

class Program
{
   static void Main(string[] args)
   {
      var context = new Model1Container();
      var mainEntity = context.MainEntities.Include("EntityTypeA").SingleOrDefault();
      context.DeleteObject(mainEntity);
      context.SaveChanges();
   }
}

Que se passe-t-il

Lorsque j'appelle SaveChanges, Entity Framework exécute les éléments suivants dans la base de données:

exec sp_executesql N'delete [dbo].[EntityTypeA]
where ([Id] = @0)',N'@0 int',@0=1

Cela provoque une violation de clé étrangère, car il existe des éléments dans la table EntityTypeB référençant les instances EntityTypeA.

Question

Pourquoi Entity Framework émet-il une suppression explicite pour l'instance d'EntityTypeA même si j'ai configuré Entity Framework pour utiliser les suppressions en cascade? Si je supprime le Include ("EntityTypeA"), il recommence à fonctionner.

29
Nitramk

C'est exactement la manière dont les suppressions en cascade se comportent dans EF. La définition de la cascade sur une relation dans EF Designer demande à EF d'exécuter l'instruction DELETE pour chaque entité réelle chargée. Cela ne dit rien sur ON CASCADE DELETE dans la base de données.

La définition de la suppression en cascade lors de l'utilisation d'EF nécessite deux étapes:

  • Réglez Cascade sur la relation dans EF designer. Ceci indique au contexte que toutes les entités liées chargées doivent être supprimées avant la suppression de l'entité parent. Si cela ne se produit pas, EF lèvera une exception car l'état interne détectera que les enfants chargés ne sont liés à aucune entité parent existante, même la relation est requise. Je ne sais pas si cela se produit avant l'exécution de l'instruction delete de l'entité parent ou après, mais il n'y a aucune différence. EF ne recharge pas les entités liées après l'exécution des modifications, donc il ne sait tout simplement pas les suppressions en cascade déclenchées dans la base de données.
  • Ensemble ON CASCADE DELETE sur la relation dans la base de données. Cela demandera à SQL de supprimer tous les enregistrements associés qui n'ont pas été chargés dans le contexte au moment de la suppression du parent.

L'implémentation des suppressions en cascade dans EF est étrange et assez inefficace, mais c'est ainsi qu'elle se comporte et si vous souhaitez l'utiliser, vous devez modifier votre application pour qu'elle se comporte correctement dans ce scénario.

41
Ladislav Mrnka

Au lieu de sur le concepteur EF, on peut également définir la suppression en cascade sur les contraintes FK dans la base de données.

Voici les étapes visuelles de Sql Server Management Studio (SSMS) sur la configuration des suppressions en cascade.

Notez que lorsque vous avez terminé, n'oubliez pas de mettre à jour l'edmx par rapport à la base de données avant de tenter une suppression.

enter image description here

J'en discute plus en détail sur mon blog: Entity Framework Cascading Deletes; Réglez-le à partir de la base de données.

5
ΩmegaMan