Sdílet prostřednictvím


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 hlavní/nadřazená entita odstraněna, hodnoty cizího klíče závislých/podřízených entit již nebudou odpovídat primárnímu nebo alternativnímu klíči žádné hlavní/nadřazené entity. 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í.

Návod

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

Návod

Veškerý kód v tomto dokumentu můžete spustit a ladit stažením ukázkového kódu z GitHubu.

Když dochází ke kaskádovým chováním

Kaskádové odstranění jsou potřeba, když závislá nebo podřízená entita již nemůže být přidružena k jejímu aktuálnímu hlavnímu nebo nadřazenému objektu. 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í hlavního subjektu nebo nadřazeného objektu

Zvažte tento jednoduchý model, kde Blog je nadřazený nebo rodič ve vztahu se závislým nebo podřízeným 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í možné nastavit na hodnotu null. Požadované relace jsou nakonfigurované tak, aby ve výchozím nastavení používaly kaskádové odstranění. Další informace o modelování vztahů najdete v části Vztahy.

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

using var context = new BlogsContext();

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

context.Remove(blog);

await context.SaveChangesAsync();

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;

Přerušení vztahu

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 = await context.Blogs.OrderBy(e => e.Name).Include(e => e.Posts).FirstAsync();

foreach (var post in blog.Posts)
{
    post.Blog = null;
}

await context.SaveChangesAsync();

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

using var context = new BlogsContext();

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

blog.Posts.Clear();

await context.SaveChangesAsync();

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 hlavnímu nebo závislému objektu, se označuje jako "odstranění osamocených objektů".

Návod

Kaskádové odstranění a odstranění osamocených záznamů úzce souvisí. Oba mají za následek odstranění závislých/podřízených entit, pokud je vztah k jejich požadovanému hlavnímu/rodičovskému subjektu přerušen. V případě kaskádového odstranění dojde k tomuto přerušení, protože se odstraní hlavní objekt nebo nadřazený objekt. U sirotků stále existuje hlavní/nadřazená entita, ale už není ve vztahu k závislým/podřízeným entitám.

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á.

Návod

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 konfiguruje tyto chování na základě chování kaskádového mazání v modelu EF Core při vytvoření databáze pomocí EnsureCreated nebo migrací 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. Například:

using var context = new BlogsContext();

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

context.Remove(blog);

await context.SaveChangesAsync();

Všimněte si, že pro příspěvky nejsou žádné Include, a proto 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 tyto příspěvky odstraní, protože byla nakonfigurována ON DELETE CASCADE při jejím vytvoření.

Poznámka:

Databáze obvykle nemají žádný způsob, jak automaticky odstranit osiřelé záznamy. 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.

Výstraha

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

Omezení kaskád v databázi

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é (i když poněkud přísné v zásadách správy blogů!), ale pokus o vytvoření databáze SQL Serveru s těmito nakonfigurovanými kaskádami způsobí následující výjimku:

Microsoft.Data.SqlClient.SqlException (0x80131904): Aktivace cizího klíče 'FK_Posts_Person_AuthorId' na tabulce 'Posts' může způsobit cykly nebo více kaskádových cest. Zadejte ON DELETE NO ACTION nebo ON UPDATE NO ACTION, nebo upravte další omezení CIZÍHO KLÍČE.

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

  1. Změňte jednu nebo více relací tak, aby nepoužívaly kaskádové odstranění.
  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 použití prvního přístupu v našem příkladu bychom mohli vztah mezi příspěvkem a blogem učinit volitelným tím, že přiřadíme vlastnost cizího klíče, která může mít hodnotu 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 = await context.People.SingleAsync(e => e.Name == "ajcvickers");
var blog = await context.Blogs.SingleAsync(e => e.Owner == owner);

context.Remove(owner);

await context.SaveChangesAsync();

EF Core bude kaskádově odstraňovat vlastníka, takže se odstraní i blog.

-- 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 = await context.People.SingleAsync(e => e.Name == "ajcvickers");

context.Remove(owner);

await context.SaveChangesAsync();

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_People_OwnerId". Došlo ke konfliktu v databázi "Scratch", tabulka "dbo. Blogy", sloupec OwnerId. Příkaz byl ukončen.

Kaskádové nulové hodnoty

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, když je aktuální hlavní objekt/rodič odstraněn nebo odpojen od závislého/podřízeného.

Podívejme se znovu na příklady z Když dojde kaskádovému chování, ale tentokrát s volitelnou relací reprezentovanou vlastností cizího klíče s nulovou Post.BlogId hodnotou.

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 = await context.Blogs.OrderBy(e => e.Name).Include(e => e.Posts).FirstAsync();

context.Remove(blog);

await context.SaveChangesAsync();

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 = await context.Blogs.OrderBy(e => e.Name).Include(e => e.Posts).FirstAsync();

foreach (var post in blog.Posts)
{
    post.Blog = null;
}

await context.SaveChangesAsync();

Nebo:

using var context = new BlogsContext();

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

blog.Posts.Clear();

await context.SaveChangesAsync();

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, je výchozím chováním Entity Frameworku od jeho první verze v roce 2008. Před EF Core neměl název a nebylo možné ho změnit. Jak je popsáno v další části, teď se to nazývá ClientSetNull.

Databáze lze také nakonfigurovat tak, aby při odstranění hlavního nebo nadřazeného objektu ve volitelné relaci kaskádovaly 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 nulových hodnot současně v databázi téměř vždy povede k cyklům vztahů 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í

Návod

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. Napří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
Kaskáda PŘI ODSTRANĚNÍ KASKÁDY
Omezit ON DELETE RESTRICT (při odstranění omezit)
Žádná akce výchozí nastavení databáze
SetNull PŘI ODSTRANĚNÍ NASTAVIT NULL
NastaveníKlientaNaNull 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, spočívá v tom, kdy databáze kontroluje omezení. Zkontrolujte dokumentaci k databázi, abyste našli konkrétní rozdíly mezi ON DELETE NO ACTION a ON DELETE RESTRICT ve vašem databázovém systému.

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 popisují, co se stane se závislými/podřízenými entitami, když je nadřazená entita odstraněna nebo když je přerušen její vztah k těmto 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čítání a sledování závislých/podřízených položek v DbContext a při jejich existenci pouze v databázi

Požadovaný vztah s načtenými závislými osobami/dětmi

DeleteBehavior Při odstraňování hlavního objektu nebo nadřazeného objektu Při oddělení od hlavního nebo nadřazeného objektu
Kaskáda Závislé položky odstraněné EF Core Závislé položky odstraněné EF Core
Omezit InvalidOperationException InvalidOperationException
Žádná akce InvalidOperationException InvalidOperationException
SetNull SqlException při vytváření databáze SqlException při vytváření databáze
NastaveníKlientaNaNull 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 chybu z InvalidOperationException EF Core, protože neplatný stav je zjištěn v načtených objektech podřízených/závislých.
    • ClientNoAction přinutí EF Core, aby před jejich odesláním do databáze nekontrolovala fixup závislých entit, takže v tomto případě databáze vyvolá výjimku, která je poté zabalená do DbUpdateException v rámci SaveChanges.
    • SetNull je odmítnut při vytváření databáze, protože sloupec cizího klíče není nulový.
  • Vzhledem k tomu, že jsou načteni závislé osoby nebo děti, EF Core je vždy smaže a nikdy nenechá na databázi, aby je odstranila.

Požadovaný vztah se závislými osobami/dětmi nebyl načten

DeleteBehavior Při odstraňování hlavního objektu nebo nadřazeného objektu Při oddělení od hlavního nebo nadřazeného objektu
Kaskáda Závislé položky odstraněné databází není k dispozici
Omezit DbUpdateException není k dispozici
Žádná akce DbUpdateException není k dispozici
SetNull SqlException při vytváření databáze není k dispozici
NastaveníKlientaNaNull DbUpdateException není k dispozici
ClientCascade DbUpdateException není k dispozici
ClientNoAction DbUpdateException není k dispozici

Poznámky:

  • Ukončení vztahu zde není platné, protože závislé osoby/děti 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 DbUpdateException proto, že závislé/podřízené položky nejsou načteny, a neplatný stav může zjistit pouze databáze. SaveChanges pak zabalí výjimku databáze do značky DbUpdateException.
    • SetNull je odmítnut při vytváření databáze, protože sloupec cizího klíče není nulový.

Volitelný vztah se zapnutými závislými/osobami na někom závislými

DeleteBehavior Při odstraňování hlavního objektu nebo nadřazeného objektu Při oddělení od hlavního nebo nadřazeného objektu
Kaskáda 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
Žádná akce 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
NastaveníKlientaNaNull 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 tato, je ClientSetNull.
  • Závislé osoby/děti se nikdy neodstraní, pokud Cascade nebo ClientCascade nejsou nakonfigurovány.
  • Všechny ostatní hodnoty způsobí, že závislé FKs se nastaví na hodnotu null, kterou určí EF Core.
    • ... s výjimkou ClientNoAction toho, že EF Core nemá při odstranění hlavního nebo rodičovského objektu měnit cizí klíče závislých/podřízených objektů. Databáze proto vyvolá výjimku, která je zabalena jako DbUpdateException SaveChanges.

Nepovinný vztah se závislými/dětmi, který nebyl načten

DeleteBehavior Při odstraňování hlavního objektu nebo nadřazeného objektu Při oddělení od hlavního nebo nadřazeného objektu
Kaskáda Závislé položky odstraněné databází není k dispozici
Omezit DbUpdateException není k dispozici
Žádná akce DbUpdateException není k dispozici
SetNull Závislé sady FK nastavené na hodnotu null podle databáze není k dispozici
NastaveníKlientaNaNull DbUpdateException není k dispozici
ClientCascade DbUpdateException není k dispozici
ClientNoAction DbUpdateException není k dispozici

Poznámky:

  • Ukončení vztahu zde není platné, protože závislé osoby/děti nejsou načteny.
  • Výchozí hodnota pro volitelné relace, jako je tato, je ClientSetNull.
  • Závislé osoby/potomci musí být načteni, aby se zabránilo výjimce databáze, pokud nebyla databáze nakonfigurována tak, aby kaskádově odstraňovala nebo nastavovala nulové hodnoty.