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