Kaskádové odstranění

Entity Framework Core (EF Core) představuje relace pomocí cizích klíčů. Entita s cizím klíčem je podřízená nebo závislá entita v relaci. Hodnota cizího klíče této entity musí odpovídat hodnotě primárního klíče (nebo alternativní hodnotě klíče) souvisejícího objektu zabezpečení nebo nadřazené entity.

Pokud je objekt zabezpečení nebo nadřazená entita odstraněna, hodnoty cizího klíče závislých/podřízených objektů již nebudou odpovídat primárnímu nebo alternativnímu klíči objektu zabezpečení nebo nadřazeného objektu. Toto je neplatný stav a ve většině databází způsobí porušení referenčního omezení.

Existují dvě možnosti, jak se vyhnout tomuto porušení referenčního omezení:

  1. Nastavení hodnot FK na hodnotu null
  2. Odstraňte také závislé nebo podřízené entity.

První možnost je platná pouze pro volitelné relace, kde vlastnost cizího klíče (a sloupec databáze, na který je mapován), musí být nullable.

Druhá možnost je platná pro jakýkoli druh relace a označuje se jako kaskádové odstranění.

Tip

Tento dokument popisuje kaskádové odstranění (a odstranění osamocených) z pohledu aktualizace databáze. Využívá velké využití konceptů zavedených ve službě Change Tracking v EF Core a změně cizích klíčů a navigace. Před řešením tohoto materiálu se ujistěte, že tyto koncepty plně rozumíte.

Tip

Celý kód v tomto dokumentu můžete spustit a ladit tak, že si stáhnete ukázkový kód z GitHubu.

Při kaskádových chováních dochází

Kaskádové odstranění jsou potřeba v případě, že závislá/podřízená entita již nemůže být přidružena k aktuálnímu objektu zabezpečení nebo nadřazenosti. K tomu může dojít, protože objekt zabezpečení nebo nadřazený objekt je odstraněný nebo k němu může dojít, když objekt zabezpečení nebo nadřazený objekt stále existuje, ale závislý/podřízený objekt už k němu není přidružený.

Odstranění objektu zabezpečení nebo nadřazeného objektu

Vezměte v úvahu tento jednoduchý model, kde Blog je objekt zabezpečení nebo nadřazený objekt ve vztahu se závislým/podřízeným objektem Post. Post.BlogId je vlastnost cizího klíče, jehož hodnota musí odpovídat Blog.Id primárnímu klíči blogu, ke kterému příspěvek patří.

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; }
}

Podle konvence je tato relace nakonfigurována jako povinná, protože vlastnost cizího Post.BlogId klíče není nullable. Požadované relace jsou nakonfigurované tak, aby ve výchozím nastavení používaly kaskádové odstranění. Další informace o relacích modelování najdete v tématu Relace .

Při odstraňování blogu se odstraní všechny příspěvky. Příklad:

using var context = new BlogsContext();

var blog = context.Blogs.OrderBy(e => e.Name).Include(e => e.Posts).First();

context.Remove(blog);

context.SaveChanges();

Funkce SaveChanges vygeneruje následující SQL pomocí SQL Serveru jako příklad:

-- 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;

Dělení relace

Místo odstranění blogu bychom místo toho mohli oddělit vztah mezi jednotlivými příspěvky a jeho blogem. To lze provést nastavením referenční navigace Post.Blog na hodnotu null pro každý příspěvek:

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();

Vztah může být také přerušen odebráním každého příspěvku Blog.Posts z navigace kolekce:

using var context = new BlogsContext();

var blog = context.Blogs.OrderBy(e => e.Name).Include(e => e.Posts).First();

blog.Posts.Clear();

context.SaveChanges();

V obou případech je výsledek stejný: blog se neodstraní, ale příspěvky, které už nejsou přidružené k žádnému blogu, se odstraní:

-- 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;

Odstranění entit, které už nejsou přidružené k žádnému objektu zabezpečení nebo závislému objektu, se označuje jako "odstranění osamocených objektů".

Tip

Kaskádové odstranění a odstranění osamocených objektů úzce souvisí. Oba mají za následek odstranění závislých/podřízených entit, pokud je vztah k požadovanému objektu zabezpečení nebo nadřazenosti přerušen. V případě kaskádového odstranění dojde k tomuto dělení, protože se odstraní objekt zabezpečení nebo nadřazený objekt. U osamocených objektů stále existuje objekt zabezpečení nebo nadřazená entita, ale už nesouvisí se závislými/podřízenými entitami.

Kde dochází k kaskádové chování

Kaskádové chování lze použít na:

  • Entity sledované aktuálním DbContext
  • Entity v databázi, které nebyly načteny do kontextu

Kaskádové odstranění sledovaných entit

EF Core vždy používá nakonfigurované kaskádové chování pro sledované entity. To znamená, že pokud aplikace načte všechny relevantní závislé/podřízené entity do DbContext, jak je znázorněno v příkladech výše, kaskádové chování se použije správně bez ohledu na to, jak je databáze nakonfigurovaná.

Tip

Přesné načasování, kdy se kaskádové chování děje se sledovanými entitami, lze řídit pomocí ChangeTracker.CascadeDeleteTiming a ChangeTracker.DeleteOrphansTiming. Další informace najdete v tématu Změna cizích klíčů a navigace.

Kaskádové odstranění v databázi

Mnoho databázových systémů také nabízí kaskádové chování, které se aktivuje při odstranění entity v databázi. EF Core toto chování konfiguruje na základě kaskádového chování odstranění v modelu EF Core při vytvoření databáze pomocí EnsureCreated migrace EF Core nebo EF Core. Například pomocí výše uvedeného modelu se pro příspěvky při použití SQL Serveru vytvoří následující tabulka:

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
);

Všimněte si, že omezení cizího klíče definující vztah mezi blogy a příspěvky je nakonfigurováno s ON DELETE CASCADE.

Pokud víme, že je databáze nakonfigurovaná takto, můžeme odstranit blog bez prvního načtení příspěvků a databáze se postará o odstranění všech příspěvků souvisejících s tímto blogem. Příklad:

using var context = new BlogsContext();

var blog = context.Blogs.OrderBy(e => e.Name).First();

context.Remove(blog);

context.SaveChanges();

Všimněte si, že pro příspěvky nejsou žádné Include , takže se nenačtou. SaveChanges v tomto případě odstraní jenom blog, protože se jedná o jedinou sledovaný entitu:

-- Executed DbCommand (6ms) [Parameters=[@p0='1'], CommandType='Text', CommandTimeout='30']
SET NOCOUNT ON;
DELETE FROM [Blogs]
WHERE [Id] = @p0;
SELECT @@ROWCOUNT;

To by vedlo k výjimce v případě, že omezení cizího klíče v databázi není nakonfigurováno pro kaskádové odstranění. V tomto případě však databáze příspěvky odstraní, protože byla nakonfigurována ON DELETE CASCADE při jeho vytvoření.

Poznámka:

Databáze obvykle nemají žádný způsob, jak automaticky odstranit osamocené osamocené. Je to proto, že zatímco EF Core představuje relace pomocí navigace i cizích klíčů, databáze mají pouze cizí klíče a žádné navigace. To znamená, že obvykle není možné oddělit relaci bez načtení obou stran do DbContext.

Poznámka:

Databáze EF Core v paměti v současné době nepodporuje kaskádové odstranění v databázi.

Upozorňující

Při obnovitelném odstranění entit nekonfigurujte kaskádové odstranění v databázi. To může způsobit, že se entity omylem odstraní místo obnovitelného odstranění.

Omezení kaskádové databáze

Některé databáze, zejména SQL Server, mají omezení kaskádového chování, která tvoří cykly. Představte si například následující model:

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; }
}

Tento model má tři relace, všechny požadované a nakonfigurované pro kaskádové odstranění podle konvence:

  • Odstranění blogu kaskádně odstraní všechny související příspěvky.
  • Odstranění autora příspěvků způsobí kaskádové odstranění vytvořených příspěvků.
  • Odstranění vlastníka blogu způsobí kaskádové odstranění blogu.

To je všechno rozumné (pokud je trochu drakonian v zásadách správy blogů!), ale pokus o vytvoření databáze SQL Serveru s těmito kaskádovými nakonfigurovanými výsledky způsobí následující výjimku:

Microsoft.Data.SqlClient.SqlException (0x80131904): Představujeme omezení CIZÍHO KLÍČE FK_Posts_Person_AuthorId v tabulce Příspěvky může způsobit cykly nebo více kaskádových cest. Zadejte ON DELETE NO ACTION nebo ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.

Existují dva způsoby, jak tuto situaci vyřešit:

  1. Změňte jednu nebo více relací tak, aby se kaskádové odstranění neodstranily.
  2. Nakonfigurujte databázi bez jednoho nebo několika těchto kaskádových odstranění a pak zajistěte, aby všechny závislé entity byly načteny, aby EF Core mohl provádět kaskádové chování.

Při prvním přístupu v našem příkladu bychom mohli vztah post-blog nepovinný tím, že mu poskytneme vlastnost cizího klíče s možnou hodnotou null:

public int? BlogId { get; set; }

Volitelný vztah umožňuje, aby příspěvek existoval bez blogu, což znamená, že kaskádové odstranění už nebude ve výchozím nastavení nakonfigurované. To znamená, že v kaskádových akcích už neexistuje cyklus a databáze se dá vytvořit bez chyby na SQL Serveru.

Když použijeme druhý přístup, můžeme zachovat požadovaný vztah vlastníka blogu a nakonfigurovat pro kaskádové odstranění, ale tuto konfiguraci použít pouze pro sledované entity, ne pro databázi:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Entity<Blog>()
        .HasOne(e => e.Owner)
        .WithOne(e => e.OwnedBlog)
        .OnDelete(DeleteBehavior.ClientCascade);
}

Co se stane, když načteme osobu i blog, který vlastní, a pak osobu odstraníme?

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 bude kaskádovat odstranění vlastníka, aby se blog odstranil také:

-- 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;

Pokud se ale blog při odstranění vlastníka nenačte:

using var context = new BlogsContext();

var owner = context.People.Single(e => e.Name == "ajcvickers");

context.Remove(owner);

context.SaveChanges();

Pak dojde k výjimce z důvodu porušení omezení cizího klíče v databázi:

Microsoft.Data.SqlClient.SqlException: Příkaz DELETE byl v konfliktu s omezením REFERENCE "FK_Blogs_Lidé_OwnerId". Došlo ke konfliktu v databázi "Scratch", tabulka "dbo. Blogy", sloupec OwnerId. Příkaz byl ukončen.

Kaskádové hodnoty null

Volitelné relace mají vlastnosti cizího klíče s možnou hodnotou null namapované na sloupce databáze s možnou hodnotou null. To znamená, že hodnota cizího klíče může být nastavena na hodnotu null při odstranění aktuálního objektu zabezpečení nebo nadřazeného objektu nebo jeho odstranění ze závislé/podřízené položky.

Pojďme se znovu podívat na příklady z při kaskádovém chování, ale tentokrát s volitelnou relací reprezentovanou vlastností cizího klíče s možnou Post.BlogId hodnotou null:

public int? BlogId { get; set; }

Tato vlastnost cizího klíče bude nastavena na hodnotu null pro každý příspěvek při odstranění souvisejícího blogu. Například tento kód, který je stejný jako předtím:

using var context = new BlogsContext();

var blog = context.Blogs.OrderBy(e => e.Name).Include(e => e.Posts).First();

context.Remove(blog);

context.SaveChanges();

Výsledkem budou nyní následující aktualizace databáze při zavolání SaveChanges:

-- 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;

Podobně platí, že pokud je vztah přerušen pomocí některého z výše uvedených příkladů:

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();

Nebo:

using var context = new BlogsContext();

var blog = context.Blogs.OrderBy(e => e.Name).Include(e => e.Posts).First();

blog.Posts.Clear();

context.SaveChanges();

Potom se příspěvky aktualizují o hodnoty cizího klíče null při zavolání SaveChanges:

-- 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;

Další informace o tom, jak EF Core spravuje cizí klíče a navigace při změně jejich hodnot, najdete v tématu Změna cizích klíčů a navigace.

Poznámka:

Oprava relací, jako je tato, byla výchozím chováním entity Framework od první verze v roce 2008. Před EF Core neměl název a nebylo možné ho změnit. Teď se označuje, jak ClientSetNull je popsáno v další části.

Databáze je také možné nakonfigurovat tak, aby při odstranění objektu zabezpečení nebo nadřazeného objektu v volitelné relaci kaskádovaly hodnoty null. To je ale mnohem méně běžné než použití kaskádových odstranění v databázi. Použití kaskádových odstranění a kaskádových hodnot null v databázi ve stejnou dobu bude téměř vždy vést k cyklům relací při použití SQL Serveru. Další informace o konfiguraci kaskádových hodnot null najdete v další části.

Konfigurace kaskádových chování

Tip

Než sem přijdete, nezapomeňte si přečíst výše uvedené části. Možnosti konfigurace pravděpodobně nebudou dávat smysl, pokud předchozí materiál není srozumitelný.

Kaskádové chování se konfiguruje pro každou relaci pomocí OnDelete metody v OnModelCreating. Příklad:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Entity<Blog>()
        .HasOne(e => e.Owner)
        .WithOne(e => e.OwnedBlog)
        .OnDelete(DeleteBehavior.ClientCascade);
}

Další informace o konfiguraci relací mezi typy entit najdete v tématu Relace .

OnDelete přijímá hodnotu z, nepochybně matoucí, DeleteBehavior výčtu. Tento výčet definuje chování EF Core u sledovaných entit a konfiguraci kaskádového odstranění v databázi při použití EF k vytvoření schématu.

Dopad na schéma databáze

Následující tabulka ukazuje výsledek každé OnDelete hodnoty omezení cizího klíče vytvořeného migrací EF Core nebo EnsureCreated.

DeleteBehavior Dopad na schéma databáze
Cascade PŘI ODSTRANĚNÍ KASKÁDY
Omezit ON DELETE RESTRICT
NoAction výchozí nastavení databáze
SetNull PŘI ODSTRANĚNÍ SET NULL
ClientSetNull výchozí nastavení databáze
ClientCascade výchozí nastavení databáze
ClientNoAction výchozí nastavení databáze

Chování ON DELETE NO ACTION (výchozí nastavení databáze) a ON DELETE RESTRICT v relačních databázích jsou obvykle identické nebo velmi podobné. I přes to, co NO ACTION může znamenat, obě tyto možnosti způsobují vynucení referenčních omezení. Rozdíl, pokud existuje, je , když databáze kontroluje omezení. Konkrétní rozdíly mezi ON DELETE NO ACTION databázovým systémem a ON DELETE RESTRICT databázovým systémem najdete v dokumentaci k databázi.

SQL Server nepodporuje ON DELETE RESTRICT, takže ON DELETE NO ACTION se používá místo toho.

Jediné hodnoty, které způsobí kaskádové chování v databázi, jsou Cascade a SetNull. Všechny ostatní hodnoty nakonfigurují databázi tak, aby nepřišly kaskádové změny.

Dopad na chování SaveChanges

Tabulky v následujících částech se týkají toho, co se stane se závislými/podřízenými entitami při odstranění objektu zabezpečení nebo nadřazeného objektu nebo jeho vztahu k závislým/podřízeným entitám. Každá tabulka obsahuje jednu z těchto možností:

  • Volitelné (FK s možnou hodnotou null) a požadované relace (nenulovatelné FK)
  • Při načtení a sledování závislých/podřízených položek dbContext a jejich existence pouze v databázi

Požadovaný vztah se načtenými závislými/podřízenými objekty

DeleteBehavior Při odstraňování objektu zabezpečení nebo nadřazeného objektu Při dělení z objektu zabezpečení nebo nadřazeného objektu
Cascade Závislé položky odstraněné ef Core Závislé položky odstraněné ef Core
Omezit InvalidOperationException InvalidOperationException
NoAction InvalidOperationException InvalidOperationException
SetNull SqlException při vytváření databáze SqlException při vytváření databáze
ClientSetNull InvalidOperationException InvalidOperationException
ClientCascade Závislé položky odstraněné ef Core Závislé položky odstraněné ef Core
ClientNoAction DbUpdateException InvalidOperationException

Poznámky:

  • Výchozí hodnota požadovaných relací je Cascade.
  • Při použití jiného než kaskádového odstranění požadovaných relací dojde k výjimce při zavolání SaveChanges.
    • Obvykle se jedná o ef InvalidOperationException Core, protože v načtených podřízených/závislých objektech se zjistí neplatný stav.
    • ClientNoAction Vynutí EF Core, aby před jejich odesláním do databáze nezkontrolovala závislé funkce EF Core, takže v tomto případě databáze vyvolá výjimku, která se pak zabalí do DbUpdateException funkce SaveChanges.
    • SetNull při vytváření databáze se odmítne, protože sloupec cizího klíče nemá hodnotu null.
  • Vzhledem k tomu, že jsou načítány závislé osoby nebo podřízené položky, ef Core je vždy odstraní a databáze se nikdy neodstraní.

Požadovaný vztah se závislými/podřízenými objekty se nenačetl

DeleteBehavior Při odstraňování objektu zabezpečení nebo nadřazeného objektu Při dělení z objektu zabezpečení nebo nadřazeného objektu
Cascade Závislé položky odstraněné databází
Omezit DbUpdateException
NoAction DbUpdateException
SetNull SqlException při vytváření databáze
ClientSetNull DbUpdateException
ClientCascade DbUpdateException
ClientNoAction DbUpdateException

Poznámky:

  • Dělení relace zde není platné, protože závislé/podřízené položky nejsou načteny.
  • Výchozí hodnota požadovaných relací je Cascade.
  • Při použití jiného než kaskádového odstranění požadovaných relací dojde k výjimce při zavolání SaveChanges.
    • Obvykle je to proto DbUpdateException , že závislé/podřízené položky nejsou načteny, a proto může databáze zjistit neplatný stav. SaveChanges pak zabalí výjimku databáze do .DbUpdateException
    • SetNull při vytváření databáze se odmítne, protože sloupec cizího klíče nemá hodnotu null.

Volitelný vztah se načtenými závislými/podřízenými objekty

DeleteBehavior Při odstraňování objektu zabezpečení nebo nadřazeného objektu Při dělení z objektu zabezpečení nebo nadřazeného objektu
Cascade Závislé položky odstraněné ef Core Závislé položky odstraněné ef Core
Omezit Závislé sady FK nastavené na hodnotu null podle EF Core Závislé sady FK nastavené na hodnotu null podle EF Core
NoAction Závislé sady FK nastavené na hodnotu null podle EF Core Závislé sady FK nastavené na hodnotu null podle EF Core
SetNull Závislé sady FK nastavené na hodnotu null podle EF Core Závislé sady FK nastavené na hodnotu null podle EF Core
ClientSetNull Závislé sady FK nastavené na hodnotu null podle EF Core Závislé sady FK nastavené na hodnotu null podle EF Core
ClientCascade Závislé položky odstraněné ef Core Závislé položky odstraněné ef Core
ClientNoAction DbUpdateException Závislé sady FK nastavené na hodnotu null podle EF Core

Poznámky:

  • Výchozí hodnota pro volitelné relace, jako je ClientSetNulltato.
  • Závislé osoby nebo podřízené položky se nikdy neodstraní, pokud Cascade nejsou ClientCascade nakonfigurované.
  • Všechny ostatní hodnoty způsobí, že závislé sady FK se nastaví na hodnotu null ef Core...
    • ... s výjimkou ClientNoAction toho, že EF Core nemá při odstranění objektu zabezpečení nebo nadřazeného objektu dotýkat cizí klíče závislých/podřízených položek. Databáze proto vyvolá výjimku, která je zabalena jako DbUpdateException saveChanges.

Nepovinný vztah se závislými/podřízenými objekty, které nejsou načteny

DeleteBehavior Při odstraňování objektu zabezpečení nebo nadřazeného objektu Při dělení z objektu zabezpečení nebo nadřazeného objektu
Cascade Závislé položky odstraněné databází
Omezit DbUpdateException
NoAction DbUpdateException
SetNull Závislé sady FK nastavené na hodnotu null podle databáze
ClientSetNull DbUpdateException
ClientCascade DbUpdateException
ClientNoAction DbUpdateException

Poznámky:

  • Dělení relace zde není platné, protože závislé/podřízené položky nejsou načteny.
  • Výchozí hodnota pro volitelné relace, jako je ClientSetNulltato.
  • Závislé osoby a podřízené položky musí být načteny, aby se zabránilo výjimce databáze, pokud nebyla databáze nakonfigurována tak, aby kaskádově odstraňovala nebo null.