Les suppressions en cascade avec les entités liées à Entity Framework 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 des suppressions en cascade dans la base de données.
Ma conception:
J'ai trois types d'entité, 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 veux tous liés EntityTypeA
et EntityTypeB
instances être supprimé Aussi. 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 crash 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 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 ce qui suit 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 y a 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 de EntityTypeA même si J'ai configuré Entity Framework pour utiliser des suppressions en cascade? Si Je supprimez L'Include ("EntityTypeA") il recommence à fonctionner.
2 réponses
C'est exactement comment les suppressions en cascade se comportent dans EF. Définir Cascade sur une relation dans EF designer demande à EF d'exécuter l'instruction DELETE
pour chaque entité realated chargée. Il ne dit rien à propos de ON CASCADE DELETE
dans la base de données.
Le réglage de la suppression en Cascade lors de L'utilisation D'EF nécessite deux étapes:
- définissez Cascade sur la relation dans EF designer. Ce contexte indique que toutes les entités liées chargées doivent être supprimées avant la suppression de l'entité parente. Si cela ne se produit pas, EF lancera une exception car l'état interne détectera que les enfants chargés ne sont liés à aucune entité parente existante, même la relation est requise. Je ne suis pas sûr si cela se produit avant l'exécution de l'instruction delete de l'entité parente ou après, mais il n'y a pas de différence. EF ne recharge pas les entités associées après l'exécution des modifications, donc il ne connaît tout simplement pas les suppressions en cascade déclenchées dans la base de données.
- Définir
ON CASCADE DELETE
sur la relation dans la base de données. Ce sera demandez à 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 comme ça qu'elle se comporte et si vous voulez 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 façon de configurer les suppressions en cascade.
Remarque Lorsque vous avez terminé, n'oubliez pas de Mettre à jour l'edmx sur la base de données avant de tenter une suppression.
J'en discute plus en profondeur sur mon blog: Entity Framework Cascading Deletes; définissez-le à partir du la base de données.