Suppression en cascade
Entity Framework Core (EF Core) représente les relations à l’aide de clés étrangères. Une entité avec une clé étrangère est l’entité enfant ou dépendante dans la relation. La valeur de clé étrangère de cette entité doit correspondre à la valeur de clé primaire (ou à une autre valeur de clé) de l’entité principale/parente associée.
Si l’entité principale/parente est supprimée, les valeurs de clé étrangère des entités dépendantes/enfants ne correspondent plus à la clé primaire ou à la clé alternative d’une entité principale/parente. Il s’agit d’un état non valide, qui entraîne une violation de contrainte référentielle dans la plupart des bases de données.
Il existe deux options pour éviter cette violation de contrainte référentielle :
- Affecter la valeur null aux valeurs de clé étrangère
- Supprimer également les entités dépendantes/enfants
La première option est valide uniquement pour les relations facultatives où la propriété de clé étrangère (et la colonne de base de données à laquelle elle est mappée) doit être nullable.
La deuxième option est valide pour tous les genres de relations, et est appelée « suppression en cascade ».
Conseil
Ce document décrit les suppressions en cascade (et la suppression des orphelins) dans la perspective de la mise à jour de la base de données. Il utilise fréquemment les concepts introduits dans Suivi des modifications dans EF Core et Modification des clés étrangères et des navigations. Veillez à bien comprendre ces concepts avant d’aborder le contenu présenté ici.
Conseil
Vous pouvez exécuter et déboguer dans tout le code de ce document en téléchargeant l’exemple de code à partir de GitHub.
Quand se produisent les comportements en cascade
Les suppressions en cascade sont nécessaires quand une entité dépendante/enfant ne peut plus être associée à son entité principale/parente actuelle. Cela peut se produire à la suite de la suppression de l’entité principale/parente, ou quand l’entité principale/parente existe toujours mais que l’entité dépendante/enfant ne lui est plus associée.
Suppression d’une entité principale/parente
Prenons ce modèle simple où Blog
est l’entité principale/parente dans une relation avec Post
, qui est l’entité dépendante/enfant. Post.BlogId
est une propriété de clé étrangère, dont la valeur doit correspondre à la clé primaire Blog.Id
du blog auquel le billet appartient.
public class Blog
{
public int Id { get; set; }
public string Name { get; set; }
public IList<Post> Posts { get; } = new List<Post>();
}
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public Blog Blog { get; set; }
}
Par convention, cette relation est configurée comme étant obligatoire, car la propriété de clé étrangère Post.BlogId
est non-nullable. Les relations obligatoires sont configurées pour utiliser les suppressions en cascade par défaut. Pour plus d’informations sur la modélisation des relations, consultez Relations.
Quand vous supprimez un blog, tous les billets sont supprimés en cascade. Par exemple :
using var context = new BlogsContext();
var blog = context.Blogs.OrderBy(e => e.Name).Include(e => e.Posts).First();
context.Remove(blog);
context.SaveChanges();
SaveChanges génère le code SQL suivant, en prenant SQL Server comme exemple :
-- Executed DbCommand (1ms) [Parameters=[@p0='1'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
DELETE FROM [Posts]
WHERE [Id] = @p0;
SELECT @@ROWCOUNT;
-- Executed DbCommand (0ms) [Parameters=[@p0='2'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
DELETE FROM [Posts]
WHERE [Id] = @p0;
SELECT @@ROWCOUNT;
-- Executed DbCommand (2ms) [Parameters=[@p1='1'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
DELETE FROM [Blogs]
WHERE [Id] = @p1;
SELECT @@ROWCOUNT;
Rupture d’une relation
Au lieu de supprimer le blog, nous pouvons rompre la relation entre chaque billet et son blog. Pour ce faire, affectez la valeur null à la navigation de référence Post.Blog
pour chaque billet :
using var context = new BlogsContext();
var blog = context.Blogs.OrderBy(e => e.Name).Include(e => e.Posts).First();
foreach (var post in blog.Posts)
{
post.Blog = null;
}
context.SaveChanges();
Vous pouvez également rompre la relation en supprimant chaque billet de la navigation dans la collection Blog.Posts
:
using var context = new BlogsContext();
var blog = context.Blogs.OrderBy(e => e.Name).Include(e => e.Posts).First();
blog.Posts.Clear();
context.SaveChanges();
Dans les deux cas, le résultat est le même : le blog n’est pas supprimé, mais les billets qui ne sont plus associés à un blog sont supprimés :
-- Executed DbCommand (1ms) [Parameters=[@p0='1'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
DELETE FROM [Posts]
WHERE [Id] = @p0;
SELECT @@ROWCOUNT;
-- Executed DbCommand (0ms) [Parameters=[@p0='2'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
DELETE FROM [Posts]
WHERE [Id] = @p0;
SELECT @@ROWCOUNT;
La suppression d’entités qui ne sont plus associées à une entité principale/dépendante s’appelle la « suppression des orphelins ».
Conseil
La suppression en cascade et la suppression des orphelins sont étroitement liées. Les deux entraînent la suppression des entités dépendantes/enfants quand la relation avec leur entité principale/parente obligatoire est rompue. Dans le cas de la suppression en cascade, cette rupture se produit dans la mesure où l’entité principale/parente est elle-même supprimée. Dans le cas des orphelins, l’entité principale/parente existe toujours, mais elle n’est plus liée aux entités dépendantes/enfants.
Où se produisent les comportements en cascade
Les comportements en cascade peuvent s’appliquer aux :
- Entités suivies par le DbContext actuel
- Entités de la base de données qui n’ont pas été chargées dans le contexte
Suppression en cascade d’entités suivies
EF Core applique toujours les comportements en cascade configurés aux entités suivies. Cela signifie que si l’application charge toutes les entités dépendantes/enfants appropriées dans DbContext, comme indiqué dans les exemples ci-dessus, les comportements en cascade sont correctement appliqués, quelle que soit la configuration de la base de données.
Conseil
Le moment exact où les comportements en cascade se produisent pour les entités suivies peut être contrôlé à l’aide de ChangeTracker.CascadeDeleteTiming et ChangeTracker.DeleteOrphansTiming. Pour plus d’informations, consultez Modification des clés étrangères et des navigations.
Suppression en cascade dans la base de données
De nombreux systèmes de base de données proposent également des comportements en cascade qui se déclenchent quand une entité est supprimée dans la base de données. EF Core configure ces comportements en fonction du comportement de suppression en cascade du modèle EF Core quand une base de données est créée à l’aide de EnsureCreated ou des migrations EF Core. Par exemple, à l’aide du modèle ci-dessus, la table suivante est créée pour les billets quand vous utilisez SQL Server :
CREATE TABLE [Posts] (
[Id] int NOT NULL IDENTITY,
[Title] nvarchar(max) NULL,
[Content] nvarchar(max) NULL,
[BlogId] int NOT NULL,
CONSTRAINT [PK_Posts] PRIMARY KEY ([Id]),
CONSTRAINT [FK_Posts_Blogs_BlogId] FOREIGN KEY ([BlogId]) REFERENCES [Blogs] ([Id]) ON DELETE CASCADE
);
Notez que la contrainte de clé étrangère définissant la relation entre les blogs et les billets est configurée avec ON DELETE CASCADE
.
Si nous savons que la base de données est configurée de cette façon, nous pouvons supprimer un blog sans charger au préalable les billets. La base de données s’occupe de supprimer tous les billets liés à ce blog. Par exemple :
using var context = new BlogsContext();
var blog = context.Blogs.OrderBy(e => e.Name).First();
context.Remove(blog);
context.SaveChanges();
Notez qu’il n’existe pas de Include
pour les billets. Ils ne sont donc pas chargés. Dans ce cas, SaveChanges supprime uniquement le blog, car il s’agit de la seule entité faisant l’objet d’un suivi :
-- Executed DbCommand (6ms) [Parameters=[@p0='1'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
DELETE FROM [Blogs]
WHERE [Id] = @p0;
SELECT @@ROWCOUNT;
Cela entraîne une exception si la contrainte de clé étrangère dans la base de données n’est pas configurée pour les suppressions en cascade. Toutefois, dans ce cas, les billets sont supprimés par la base de données, car elle a été configurée avec ON DELETE CASCADE
au moment de sa création.
Remarque
En règle générale, les bases de données n’ont aucun moyen de supprimer automatiquement les orphelins. En effet, bien qu’EF Core représente les relations à l’aide de navigations et de clés étrangères, les bases de données ont uniquement des clés étrangères, et aucune navigation. Cela signifie qu’il n’est généralement pas possible de rompre une relation sans charger les deux côtés dans DbContext.
Remarque
Pour le moment, la base de données en mémoire EF Core ne prend pas en charge les suppressions en cascade dans la base de données.
Avertissement
Ne configurez pas la suppression en cascade dans la base de données au moment de la suppression réversible d’entités. Cela peut entraîner une suppression réelle accidentelle des entités à la place d’une suppression réversible.
Limitations des comportements en cascade dans les bases de données
Certaines bases de données, plus particulièrement SQL Server, ont des limitations pour les comportements en cascade qui forment les cycles. Par exemple, prenons le modèle suivant :
public class Blog
{
public int Id { get; set; }
public string Name { get; set; }
public IList<Post> Posts { get; } = new List<Post>();
public int OwnerId { get; set; }
public Person Owner { get; set; }
}
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public Blog Blog { get; set; }
public int AuthorId { get; set; }
public Person Author { get; set; }
}
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public IList<Post> Posts { get; } = new List<Post>();
public Blog OwnedBlog { get; set; }
}
Ce modèle a trois relations, toutes obligatoires, et donc configurées pour la suppression en cascade par convention :
- La suppression d’un blog entraîne la suppression en cascade de tous les billets associés
- La suppression de l’auteur des billets entraîne la suppression en cascade des billets créés
- La suppression du propriétaire d’un blog entraîne la suppression en cascade du blog
Tout cela est raisonnable (bien qu’un peu draconien dans le cadre des stratégies de gestion de blogs), mais la tentative de création d’une base de données SQL Server avec la configuration de ces cascades entraîne l’exception suivante :
Microsoft.Data.SqlClient.SqlException (0x80131904) : L’introduction de la contrainte FOREIGN KEY « FK_Posts_Person_AuthorId » sur la table « Posts » peut entraîner des problèmes de références cycliques ou de chemins en cascade multiples. Spécifiez ON DELETE NO ACTION ou ON UPDATE NO ACTION, ou modifiez d'autres contraintes FOREIGN KEY.
Il existe deux façons de gérer cette situation :
- Changez une ou plusieurs des relations pour ne pas effectuer de suppressions en cascade.
- Configurez la base de données sans une ou plusieurs de ces suppressions en cascade, puis vérifiez que toutes les entités dépendantes sont chargées pour qu’EF Core puisse appliquer le comportement en cascade.
En adoptant la première approche avec notre exemple, nous pouvons rendre la relation billet-blog facultative en lui affectant une propriété de clé étrangère nullable :
public int? BlogId { get; set; }
Une relation facultative permet au blog d’exister sans un billet, ce qui signifie que la suppression en cascade ne sera plus configurée par défaut. Cela signifie qu’il n’existe plus de cycle dans les actions en cascade, et que la base de données peut être créée sans erreur sur SQL Server.
En revanche, en adoptant la deuxième approche, nous pouvons maintenir la relation entre le blog et le propriétaire obligatoire, et configurée pour une suppression en cascade, tout en faisant en sorte que cette configuration s’applique uniquement aux entités suivies, et non à la base de données :
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Blog>()
.HasOne(e => e.Owner)
.WithOne(e => e.OwnedBlog)
.OnDelete(DeleteBehavior.ClientCascade);
}
Que se passe-t-il si nous chargeons à la fois une personne et son blog, et si nous supprimons ensuite cette personne ?
using var context = new BlogsContext();
var owner = context.People.Single(e => e.Name == "ajcvickers");
var blog = context.Blogs.Single(e => e.Owner == owner);
context.Remove(owner);
context.SaveChanges();
EF Core applique la suppression en cascade au propriétaire pour que le blog soit également supprimé :
-- Executed DbCommand (8ms) [Parameters=[@p0='1'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
DELETE FROM [Blogs]
WHERE [Id] = @p0;
SELECT @@ROWCOUNT;
-- Executed DbCommand (2ms) [Parameters=[@p1='1'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
DELETE FROM [People]
WHERE [Id] = @p1;
SELECT @@ROWCOUNT;
Toutefois, si le blog n’est pas chargé au moment de la suppression du propriétaire :
using var context = new BlogsContext();
var owner = context.People.Single(e => e.Name == "ajcvickers");
context.Remove(owner);
context.SaveChanges();
Une exception est levée en raison d’une violation de la contrainte de clé étrangère dans la base de données :
Microsoft.Data.SqlClient.SqlException : L’instruction DELETE est en conflit avec la contrainte REFERENCE « FK_Blogs_People_OwnerId ». Le conflit s’est produit dans la base de données « Scratch », la table « dbo.Blogs », la colonne « OwnerId ». L'instruction a été arrêtée.
Valeurs nulles en cascade
Les relations facultatives ont des propriétés de clé étrangère nullables, mappées à des colonnes de base de données nullables. Cela signifie que la valeur de clé étrangère peut être nulle quand l’entité principale/parente actuelle est supprimée ou séparée de l’entité dépendante/enfant.
Examinons à nouveau les exemples décrits dans la section Quand se produisent les comportements en cascade, mais cette fois avec une relation facultative représentée par une propriété de clé étrangère Post.BlogId
nullable :
public int? BlogId { get; set; }
Cette propriété de clé étrangère a la valeur null pour chaque billet quand son blog associé est supprimé. Ce code, par exemple, qui est le même que précédemment :
using var context = new BlogsContext();
var blog = context.Blogs.OrderBy(e => e.Name).Include(e => e.Posts).First();
context.Remove(blog);
context.SaveChanges();
Entraîne désormais les mises à jour de base de données suivantes quand SaveChanges est appelé :
-- Executed DbCommand (2ms) [Parameters=[@p1='1', @p0=NULL (DbType = Int32)], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
UPDATE [Posts] SET [BlogId] = @p0
WHERE [Id] = @p1;
SELECT @@ROWCOUNT;
-- Executed DbCommand (0ms) [Parameters=[@p1='2', @p0=NULL (DbType = Int32)], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
UPDATE [Posts] SET [BlogId] = @p0
WHERE [Id] = @p1;
SELECT @@ROWCOUNT;
-- Executed DbCommand (1ms) [Parameters=[@p2='1'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
DELETE FROM [Blogs]
WHERE [Id] = @p2;
SELECT @@ROWCOUNT;
De même, si la relation est rompue à l’aide de l’un des exemples ci-dessus :
using var context = new BlogsContext();
var blog = context.Blogs.OrderBy(e => e.Name).Include(e => e.Posts).First();
foreach (var post in blog.Posts)
{
post.Blog = null;
}
context.SaveChanges();
Ou :
using var context = new BlogsContext();
var blog = context.Blogs.OrderBy(e => e.Name).Include(e => e.Posts).First();
blog.Posts.Clear();
context.SaveChanges();
Les billets sont ensuite mis à jour avec des valeurs de clé étrangère nulles quand SaveChanges est appelé :
-- Executed DbCommand (2ms) [Parameters=[@p1='1', @p0=NULL (DbType = Int32)], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
UPDATE [Posts] SET [BlogId] = @p0
WHERE [Id] = @p1;
SELECT @@ROWCOUNT;
-- Executed DbCommand (0ms) [Parameters=[@p1='2', @p0=NULL (DbType = Int32)], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
UPDATE [Posts] SET [BlogId] = @p0
WHERE [Id] = @p1;
SELECT @@ROWCOUNT;
Consultez Modification des clés étrangères et des navigations pour plus d’informations sur la façon dont EF Core gère les clés étrangères et les navigations au fur et à mesure que leurs valeurs changent.
Remarque
La correction des relations de cette façon est le comportement par défaut d’Entity Framework depuis la première version en 2008. Avant EF Core, ce comportement n’avait pas de nom et ne pouvait pas être changé. Il est désormais appelé ClientSetNull
, comme indiqué dans la section suivante.
Les bases de données peuvent également être configurées pour utiliser des valeurs nulles en cascade de cette façon, quand une entité principale/parente d’une relation facultative est supprimée. Toutefois, il s’agit d’une opération beaucoup moins courante que l’utilisation de suppressions en cascade dans la base de données. L’utilisation simultanée de suppressions en cascade et de valeurs nulles en cascade dans la base de données entraîne presque toujours l’apparition de problèmes de cycles dans les relations quand SQL Server est utilisé. Pour plus d’informations sur la configuration des valeurs nulles en cascade, consultez la section suivante.
Configuration des comportements en cascade
Conseil
Veillez à lire les sections ci-dessus avant de poursuivre la lecture de ce contenu. Les options de configuration n’auront probablement aucun sens si les informations précédentes ne sont pas comprises.
Les comportements en cascade sont configurés par relation à l’aide de la méthode OnDelete dans OnModelCreating. Par exemple :
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder
.Entity<Blog>()
.HasOne(e => e.Owner)
.WithOne(e => e.OwnedBlog)
.OnDelete(DeleteBehavior.ClientCascade);
}
Pour plus d’informations sur la configuration des relations entre les types d’entités, consultez Relations.
OnDelete
accepte une valeur provenant de l’enum DeleteBehavior, qui prête parfois à confusion. Cet enum définit à la fois le comportement d’EF Core sur les entités suivies ainsi que la configuration de la suppression en cascade dans la base de données quand EF est utilisé pour créer le schéma.
Impact sur le schéma de base de données
Le tableau suivant montre le résultat de chaque valeur OnDelete
sur la contrainte de clé étrangère créée par les migrations EF Core ou EnsureCreated.
DeleteBehavior | Impact sur le schéma de base de données |
---|---|
En cascade | ON DELETE CASCADE |
Restreindre | ON DELETE RESTRICT |
NoAction | comportement par défaut de la base de données |
SetNull | ON DELETE SET NULL |
ClientSetNull | comportement par défaut de la base de données |
ClientCascade | comportement par défaut de la base de données |
ClientNoAction | comportement par défaut de la base de données |
Les comportements de ON DELETE NO ACTION
(comportement par défaut de la base de données) et de ON DELETE RESTRICT
dans les bases de données relationnelles sont généralement identiques ou très similaires. Malgré ce que NO ACTION
peut impliquer, ces deux options entraînent l’application de contraintes référentielles. La différence, quand elle existe, réside dans le moment où la base de données vérifie les contraintes. Consultez la documentation de votre base de données pour connaître les différences spécifiques entre ON DELETE NO ACTION
et ON DELETE RESTRICT
au sein de votre système de base de données.
SQL Server ne prend pas en charge ON DELETE RESTRICT
. ON DELETE NO ACTION
est donc utilisé à la place.
Les seules valeurs qui entraînent des comportements en cascade dans la base de données sont Cascade
et SetNull
. Toutes les autres valeurs permettent de configurer la base de données pour qu’aucun changement ne soit effectué en cascade.
Impact sur le comportement de SaveChanges
Les tableaux des sections suivantes décrivent ce qui arrive aux entités dépendantes/enfants quand l’entité principale/parente est supprimée, ou quand sa relation avec les entités dépendantes/enfants est rompue. Chaque tableau décrit l’un des aspects suivants :
- Relations facultatives (clé étrangère nullable) et obligatoires (clé étrangère non-nullable)
- Moment où les entités dépendantes/enfants sont chargées et suivies par DbContext, et moment où elles existent uniquement dans la base de données
Relation obligatoire avec les entités dépendantes/enfants chargées
DeleteBehavior | Au moment de la suppression de l’entité principale/parente | Au moment de la rupture par rapport à l’entité principale/parente |
---|---|---|
En cascade | Entités dépendantes supprimées par EF Core | Entités dépendantes supprimées par EF Core |
Restreindre | InvalidOperationException |
InvalidOperationException |
NoAction | InvalidOperationException |
InvalidOperationException |
SetNull | SqlException au moment de la création de la base de données |
SqlException au moment de la création de la base de données |
ClientSetNull | InvalidOperationException |
InvalidOperationException |
ClientCascade | Entités dépendantes supprimées par EF Core | Entités dépendantes supprimées par EF Core |
ClientNoAction | DbUpdateException |
InvalidOperationException |
Remarques :
- La valeur par défaut pour les relations obligatoires de ce genre est
Cascade
. - L’utilisation d’un autre comportement que la suppression en cascade pour les relations obligatoires entraîne une exception quand SaveChanges est appelé.
- En règle générale, il s’agit d’une exception
InvalidOperationException
d’EF Core, car l’état non valide est détecté dans les entités enfants/dépendantes chargées. ClientNoAction
force EF Core à ne pas vérifier les entités dépendantes avant de les envoyer à la base de données. Dans ce cas, la base de données lève une exception, qui est ensuite wrappée dansDbUpdateException
par SaveChanges.SetNull
est rejeté au moment de la création de la base de données, car la colonne de clé étrangère est non-nullable.
- En règle générale, il s’agit d’une exception
- Dans la mesure où les entités dépendantes/enfants sont chargées, elles sont toujours supprimées par EF Core, et jamais par la base de données.
Relation obligatoire avec les entités dépendantes/enfants non chargées
DeleteBehavior | Au moment de la suppression de l’entité principale/parente | Au moment de la rupture par rapport à l’entité principale/parente |
---|---|---|
En cascade | Entités dépendantes supprimées par la base de données | S.O. |
Restreindre | DbUpdateException |
S.O. |
NoAction | DbUpdateException |
S.O. |
SetNull | SqlException au moment de la création de la base de données |
S.O. |
ClientSetNull | DbUpdateException |
S.O. |
ClientCascade | DbUpdateException |
S.O. |
ClientNoAction | DbUpdateException |
S.O. |
Remarques :
- La rupture d’une relation n’est pas valide ici, car les entités dépendantes/enfants ne sont pas chargées.
- La valeur par défaut pour les relations obligatoires de ce genre est
Cascade
. - L’utilisation d’un autre comportement que la suppression en cascade pour les relations obligatoires entraîne une exception quand SaveChanges est appelé.
- En règle générale, il s’agit d’une exception
DbUpdateException
, car les entités dépendantes/enfants ne sont pas chargées. L’état non valide ne peut donc être détecté que par la base de données. SaveChanges wrappe ensuite l’exception de base de données dansDbUpdateException
. SetNull
est rejeté au moment de la création de la base de données, car la colonne de clé étrangère est non-nullable.
- En règle générale, il s’agit d’une exception
Relation facultative avec les entités dépendantes/enfants chargées
DeleteBehavior | Au moment de la suppression de l’entité principale/parente | Au moment de la rupture par rapport à l’entité principale/parente |
---|---|---|
En cascade | Entités dépendantes supprimées par EF Core | Entités dépendantes supprimées par EF Core |
Restreindre | Clés étrangères d’entités dépendantes ayant une valeur null affectée par EF Core | Clés étrangères d’entités dépendantes ayant une valeur null affectée par EF Core |
NoAction | Clés étrangères d’entités dépendantes ayant une valeur null affectée par EF Core | Clés étrangères d’entités dépendantes ayant une valeur null affectée par EF Core |
SetNull | Clés étrangères d’entités dépendantes ayant une valeur null affectée par EF Core | Clés étrangères d’entités dépendantes ayant une valeur null affectée par EF Core |
ClientSetNull | Clés étrangères d’entités dépendantes ayant une valeur null affectée par EF Core | Clés étrangères d’entités dépendantes ayant une valeur null affectée par EF Core |
ClientCascade | Entités dépendantes supprimées par EF Core | Entités dépendantes supprimées par EF Core |
ClientNoAction | DbUpdateException |
Clés étrangères d’entités dépendantes ayant une valeur null affectée par EF Core |
Remarques :
- La valeur par défaut pour les relations facultatives de ce genre est
ClientSetNull
. - Les entités dépendantes/enfants ne sont jamais supprimées, sauf si
Cascade
ouClientCascade
sont configurés. - Toutes les autres valeurs entraînent l’affectation de la valeur null aux clés étrangères d’entités dépendantes par EF Core...
- ...à l’exception de
ClientNoAction
, qui indique à EF Core de ne pas toucher aux clés étrangères des entités dépendantes/enfants quand l’entité principale/parente est supprimée. La base de données lève donc une exception, qui est wrappée en tant queDbUpdateException
par SaveChanges.
- ...à l’exception de
Relation facultative avec les entités dépendantes/enfants non chargées
DeleteBehavior | Au moment de la suppression de l’entité principale/parente | Au moment de la rupture par rapport à l’entité principale/parente |
---|---|---|
En cascade | Entités dépendantes supprimées par la base de données | S.O. |
Restreindre | DbUpdateException |
S.O. |
NoAction | DbUpdateException |
S.O. |
SetNull | Clés étrangères d’entités dépendantes ayant une valeur null affectée par la base de données | S.O. |
ClientSetNull | DbUpdateException |
S.O. |
ClientCascade | DbUpdateException |
S.O. |
ClientNoAction | DbUpdateException |
S.O. |
Remarques :
- La rupture d’une relation n’est pas valide ici, car les entités dépendantes/enfants ne sont pas chargées.
- La valeur par défaut pour les relations facultatives de ce genre est
ClientSetNull
. - Les entités dépendantes/enfants doivent être chargées pour éviter une exception de base de données, sauf si la base de données a été configurée pour mettre en cascade les suppressions ou les valeurs nulles.