Udostępnij przez


Usuwanie kaskadowe

Platforma Entity Framework Core (EF Core) reprezentuje relacje przy użyciu kluczy obcych. Byt z kluczem obcym jest bytem podrzędnym lub zależnym w relacji. Wartość klucza obcego tej jednostki musi być zgodna z wartością klucza podstawowego (lub alternatywną wartością klucza) powiązanej jednostki głównej/nadrzędnej.

Jeśli jednostka główna/nadrzędna zostanie usunięta, wartości klucza obcego zależnych/podrzędnych nie będą już zgodne z kluczem podstawowym lub alternatywnym dowolnej jednostki głównej/nadrzędnej. Jest to nieprawidłowy stan i spowoduje naruszenie ograniczeń odwołań w większości baz danych.

Istnieją dwie opcje uniknięcia tego naruszenia ograniczeń odwołań:

  1. Ustawianie wartości FK na wartość null
  2. Usuń również jednostki zależne/podrzędne

Pierwsza opcja jest prawidłowa tylko w przypadku relacji opcjonalnych, w których właściwość klucza obcego (i kolumna bazy danych, do której jest mapowana) musi mieć wartość null.

Druga opcja jest prawidłowa dla dowolnego rodzaju relacji i jest nazywana "usuwaniem kaskadowym".

Wskazówka

W tym dokumencie opisano usuwanie kaskadowe (i usuwanie osieroconych) z perspektywy aktualizowania bazy danych. Wykorzystuje intensywnie pojęcia wprowadzone w Change Tracking w EF Core i Changing Foreign Keys and Navigations. Pamiętaj, aby w pełni zrozumieć te pojęcia przed przystąpieniem do pracy z materiałem tutaj.

Wskazówka

Możesz uruchomić i debugować cały kod w tym dokumencie, pobierając przykładowy kod z usługi GitHub.

W przypadku wystąpienia kaskadowych zachowań

Usuwanie kaskadowe jest wymagane, gdy jednostka zależna lub podrzędna nie może być już skojarzona z bieżącym podmiotem głównym lub elementem nadrzędnym. Może się tak zdarzyć, ponieważ byt nadrzędny jest usuwany, lub może się zdarzyć, gdy byt nadrzędny nadal istnieje, ale element zależny/podrzędny nie jest już z nim powiązany.

Usuwanie dyrektora/elementu nadrzędnego

Rozważmy ten prosty model, w którym Blog jest podmiotem nadrzędnym w relacji z Post, który jest zależny/podrzędny. Post.BlogId to właściwość klucza obcego, której wartość musi być zgodna z kluczem Blog.Id podstawowym w blogu, do którego należy wpis.

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

Zgodnie z konwencją ta relacja jest skonfigurowana jako wymagana, ponieważ klucz obcy nie akceptuje wartości null. Wymagane relacje są domyślnie skonfigurowane do używania usuwania kaskadowego. Zobacz Relacje , aby uzyskać więcej informacji na temat modelowania relacji.

Podczas usuwania bloga wszystkie wpisy są usuwane kaskadowo. Przykład:

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

Funkcja SaveChanges generuje następujący kod SQL, używając programu SQL Server jako przykładu:

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

Zerwanie relacji

Zamiast usuwać blog, możemy zamiast tego zerwać relację między każdym wpisem a blogem. Można to zrobić, ustawiając nawigację Post.Blog referencyjną na wartość null dla każdego wpisu:

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

Relację można również zerwać, usuwając każdy wpis z nawigacji kolekcji 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();

W obu przypadkach wynik jest taki sam: blog nie zostanie usunięty, ale wpisy, które nie są już skojarzone z żadnym blogiem, zostaną usunięte:

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

Usuwanie jednostek, które nie są już skojarzone z żadnym podmiotem głównym lub zależnym, jest nazywane "usuwaniem sierot".

Wskazówka

Usuwanie kaskadowe i usuwanie osieroconych są ściśle powiązane. Oba te elementy powodują usunięcie jednostek zależnych/podrzędnych, gdy relacja z wymaganym podmiotem głównym/rodzicielskim jest zerwana. W przypadku usunięcia kaskadowego rozłączenie następuje, ponieważ element główny/nadrzędny jest usuwany. W przypadku sierot jednostka główna/nadrzędna nadal istnieje, ale nie jest już powiązana z jednostkami zależnymi/podrzędnymi.

Gdzie występują zachowania kaskadowe

Zachowania kaskadowe można zastosować do:

  • Podmioty śledzone przez bieżącą DbContext
  • Jednostki w bazie danych, które nie zostały załadowane do kontekstu

Kaskadowe usuwanie śledzonych jednostek

Program EF Core zawsze stosuje skonfigurowane zachowania kaskadowe do śledzonych jednostek. Oznacza to, że jeśli aplikacja ładuje wszystkie odpowiednie jednostki zależne/podrzędne do obiektu DbContext, jak pokazano w powyższych przykładach, zachowania kaskadowe będą prawidłowo stosowane niezależnie od konfiguracji bazy danych.

Wskazówka

Dokładny czas, kiedy zachowania kaskadowe dotyczą śledzonych jednostek, może być kontrolowany przy użyciu elementów ChangeTracker.CascadeDeleteTiming i ChangeTracker.DeleteOrphansTiming. Aby uzyskać więcej informacji, zobacz Zmienianie kluczy obcych i nawigacji .

Usuwanie kaskadowe w bazie danych

Wiele systemów baz danych oferuje również kaskadowe zachowania wyzwalane po usunięciu jednostki w bazie danych. EF Core konfiguruje te zachowania na podstawie zachowania usuwania kaskadowego w modelu EF Core podczas tworzenia bazy danych przy użyciu EnsureCreated lub migracji EF Core. Na przykład przy użyciu powyższego modelu poniższa tabela jest tworzona dla wpisów podczas korzystania z programu 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
);

Zwróć uwagę, że ograniczenie klucza obcego definiujące relację między blogami i wpisami jest skonfigurowane za pomocą polecenia ON DELETE CASCADE.

Jeśli wiemy, że baza danych jest tak skonfigurowana, możemy usunąć blog bez uprzedniego ładowania wpisów , a baza danych zajmie się usunięciem wszystkich wpisów związanych z tym blogiem. Przykład:

using var context = new BlogsContext();

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

context.Remove(blog);

await context.SaveChangesAsync();

Zwróć uwagę, że nie ma Include dla wpisów, więc nie są one ładowane. Funkcja SaveChanges w tym przypadku usunie tylko blog, ponieważ jest to jedyna śledzona jednostka:

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

Spowoduje to wyjątek, jeśli ograniczenie klucza obcego w bazie danych nie jest skonfigurowane do usuwania kaskadowego. Jednak w tym przypadku posty są usuwane przez bazę danych, ponieważ została ona skonfigurowana z ON DELETE CASCADE podczas jej tworzenia.

Uwaga / Notatka

Bazy danych zwykle nie mają żadnego sposobu automatycznego usuwania osieroconych. Dzieje się tak dlatego, że EF Core reprezentuje relacje zarówno za pomocą nawigacji, jak i kluczy obcych, natomiast bazy danych mają tylko klucze obce bez nawigacji. Oznacza to, że zwykle nie można zerwać relacji bez ładowania obu stron do elementu DbContext.

Uwaga / Notatka

Baza danych EF Core używana w pamięci nie obsługuje obecnie usuwania kaskadowego.

Ostrzeżenie

Nie należy konfigurować kaskadowego usuwania w bazie danych podczas usuwania logicznego jednostek. Może to spowodować przypadkowe trwałe usunięcie jednostek zamiast usunięcia miękkiego.

Ograniczenia kaskadowe bazy danych

Niektóre bazy danych, w szczególności program SQL Server, mają ograniczenia dotyczące zachowań kaskadowych, które tworzą cykle. Rozważmy na przykład następujący 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; }
}

Ten model ma trzy relacje, wszystkie wymagane i dlatego skonfigurowane do kaskadowego usuwania według konwencji:

  • Usunięcie bloga spowoduje kaskadowe usunięcie wszystkich powiązanych wpisów
  • Usunięcie autora wpisów spowoduje, że autoryzowane wpisy zostaną usunięte kaskadowo
  • Usunięcie właściciela bloga spowoduje, że blog zostanie usunięty kaskadowo

To wszystko jest zrozumiałe (choć trochę surowe w kontekście zarządzania blogami!), ale próba utworzenia bazy danych SQL Server z tymi kaskadowymi konfiguracjami powoduje następujący wyjątek:

Microsoft.Data.SqlClient.SqlException (0x80131904): Wprowadzenie ograniczenia klucza obcego "FK_Posts_Person_AuthorId" w tabeli "Posty" może powodować cykle lub wiele kaskadowych ścieżek. Określ ON DELETE NO ACTION lub ON UPDATE NO ACTION albo zmodyfikuj inne ograniczenia KLUCZA OBCEGO.

Istnieją dwa sposoby obsługi tej sytuacji:

  1. Zmień co najmniej jedną relację, aby wyłączyć usuwanie kaskadowe.
  2. Skonfiguruj bazę danych bez co najmniej jednego z tych operacji usuwania kaskadowego, a następnie upewnij się, że wszystkie jednostki zależne są ładowane, aby program EF Core mógł wykonywać kaskadowe zachowanie.

Biorąc pod uwagę pierwsze podejście na naszym przykładzie, możemy sprawić, że relacja między postem a blogiem będzie opcjonalna, dając jej właściwość klucza obcego dopuszczającą wartość null.

public int? BlogId { get; set; }

Opcjonalna relacja umożliwia istnienie wpisu bez bloga, co oznacza, że usuwanie kaskadowe nie zostanie już skonfigurowane domyślnie. Oznacza to, że nie istnieje już cykl w akcjach kaskadowych, a baza danych może zostać utworzona bez błędu w programie SQL Server.

Zamiast tego wybierając drugie podejście, możemy zachować wymaganą relację właściciela blogu i skonfigurować ją do usunięcia kaskadowego, jednak zastosowanie tej konfiguracji będzie dotyczyć tylko śledzonych encji, a nie całej bazy danych.

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

Teraz co się stanie, jeśli załadujemy zarówno osobę, jak i blog, który jest właścicielem, a następnie usuniemy osobę?

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

Program EF Core kaskadowo usunie właściciela, aby blog również został usunięty:

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

Jeśli jednak blog nie zostanie załadowany po usunięciu właściciela:

using var context = new BlogsContext();

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

context.Remove(owner);

await context.SaveChangesAsync();

Następnie zostanie zgłoszony wyjątek z powodu naruszenia ograniczenia klucza obcego w bazie danych:

Microsoft.Data.SqlClient.SqlException: instrukcja DELETE powoduje konflikt z ograniczeniem REFERENCE "FK_Blogs_People_OwnerId". Konflikt wystąpił w bazie danych "Scratch", tabeli "dbo.Blogs", kolumna "OwnerId". Oświadczenie zostało zakończone.

Kaskadowe wartości null

Relacje opcjonalne mają właściwości klucza obcego mogące przyjmować wartość null, odpowiadające kolumnom bazy danych mogącym przyjmować wartość null. Oznacza to, że wartość klucza obcego może być ustawiona na null po usunięciu bieżącego obiektu nadrzędnego lub zerwaniu powiązania z obiektem podrzędnym.

Przyjrzyjmy się ponownie przykładom z sekcji Kiedy występują kaskadowe zachowania, ale tym razem z opcjonalną relacją reprezentowaną przez klucz obcy o wartości null Post.BlogId.

public int? BlogId { get; set; }

Ta właściwość klucza obcego zostanie ustawiona na wartość null dla każdego wpisu po usunięciu powiązanego bloga. Na przykład ten kod, który jest taki sam jak poprzednio:

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

Spowoduje to teraz następujące aktualizacje bazy danych po wywołaniu funkcji 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;

Podobnie, jeśli relacja została zerwana przy użyciu jednego z powyższych przykładów:

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

Lub:

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

Następnie wpisy są aktualizowane przy użyciu wartości klucza obcego o wartości null, gdy jest wywoływana funkcja 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;

Aby uzyskać więcej informacji na temat zarządzania kluczami obcymi i nawigacjami w miarę zmiany ich wartości, zobacz Zmienianie kluczy obcych i nawigacji w programie EF Core.

Uwaga / Notatka

Modyfikacja relacji w ten sposób jest domyślnym zachowaniem programu Entity Framework od pierwszej wersji w 2008 roku. Przed programem EF Core nie miała nazwy i nie można było jej zmienić. Jest on teraz znany jako ClientSetNull opisany w następnej sekcji.

Bazy danych można również skonfigurować do kaskadowania wartości null, gdy w relacji opcjonalnej zostanie usunięty element główny. Jednak jest to znacznie mniej powszechne niż używanie kaskadowych usunięć w bazie danych. Podczas korzystania z SQL Server, użycie kaskadowego usuwania i kaskadowego nadawania wartości NULL w bazie danych w tym samym czasie niemal zawsze będzie powodować cykle relacji. Aby uzyskać więcej informacji na temat konfigurowania kaskadowych wartości null, przeczytaj następną sekcję.

Konfigurowanie zachowań kaskadowych

Wskazówka

Pamiętaj, aby przeczytać powyższe sekcje przed przyjazdem tutaj. Opcje konfiguracji prawdopodobnie nie będą miały sensu, jeśli poprzedni materiał nie zostanie zrozumiany.

Zachowania kaskadowe są konfigurowane dla każdego związku przy użyciu metody OnDelete w OnModelCreating. Przykład:

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

Zobacz Relacje , aby uzyskać więcej informacji na temat konfigurowania relacji między typami jednostek.

OnDelete akceptuje wartość z, co prawda mylącego, wyliczenia DeleteBehavior. Wyliczenie definiuje zarówno zachowanie platformy EF Core na śledzonych jednostkach, jak i konfigurację usuwania kaskadowego w bazie danych, gdy program EF jest używany do tworzenia schematu.

Wpływ na schemat bazy danych

W poniższej tabeli przedstawiono wpływ każdej wartości OnDelete na ograniczenie klucza obcego, które zostało utworzone przez migracje EF Core lub przez EnsureCreated.

UsuńBehavior Wpływ na schemat bazy danych
Kaskada PO USUNIĘCIU KASKADY
Ograniczać PO USUNIĘCIU OGRANICZ
Brak działania domyślna baza danych
SetNull PO USUNIĘCIU USTAW WARTOŚĆ NULL
ClientSetNull domyślna baza danych
ClientCascade domyślna baza danych
ClientNoAction domyślna baza danych

Zachowania ON DELETE NO ACTION (ustawienie domyślne bazy danych) i ON DELETE RESTRICT w relacyjnych bazach danych są zazwyczaj identyczne lub bardzo podobne. Pomimo tego, co NO ACTION może oznaczać, obie te opcje powodują wymuszenie zastosowania ograniczeń związanych z odwołaniami. Różnica, gdy istnieje, polega na tym, że baza danych sprawdza ograniczenia. Zapoznaj się z dokumentacją bazy danych, aby zapoznać się z konkretnymi różnicami między ON DELETE NO ACTION i ON DELETE RESTRICT w systemie bazy danych.

SQL Server nie obsługuje ON DELETE RESTRICT, więc używany jest ON DELETE NO ACTION.

Jedynymi wartościami, które spowodują kaskadowe zachowania bazy danych, są Cascade i SetNull. Wszystkie inne wartości spowodują skonfigurowanie bazy danych tak, aby nie zmieniała się kaskadowo.

Wpływ na zachowanie funkcji SaveChanges

Tabele w poniższych sekcjach opisują, co się dzieje z jednostkami zależnymi/podrzędnymi, kiedy podmiot nadrzędny/rodzic zostanie usunięty, lub gdy jego relacja z jednostkami zależnymi/podrzędnymi zostanie zerwana. Każda tabela obejmuje jedną z:

  • Opcjonalne (FK dopuszczane do wartości null) i wymagane relacje (bez wartości null)
  • Gdy obiekty zależne/dzieci są ładowane i śledzone przez DbContext oraz gdy istnieją tylko w bazie danych

Wymagana relacja z załadowanymi zależnościami/dziećmi

UsuńBehavior Usuwanie podmiotu głównego/nadrzędnego elementu Na odłączenie od źródła/podmiotu nadrzędnego
Kaskada Zależności usunięte przez program EF Core Zależności usunięte przez program EF Core
Ograniczać InvalidOperationException InvalidOperationException
Brak działania InvalidOperationException InvalidOperationException
SetNull SqlException o tworzeniu bazy danych SqlException o tworzeniu bazy danych
ClientSetNull InvalidOperationException InvalidOperationException
ClientCascade Zależności usunięte przez program EF Core Zależności usunięte przez program EF Core
ClientNoAction DbUpdateException InvalidOperationException

Notatki:

  • Wartością domyślną dla wymaganych relacji jest następująca: Cascade.
  • Zastosowanie metody innej niż usuwanie kaskadowe dla wymaganych relacji spowoduje zgłoszenie wyjątku w momencie wywołania funkcji SaveChanges.
    • Zazwyczaj jest to element InvalidOperationException z programu EF Core, ponieważ w załadowanych elementach podrzędnych/zależnych wykryto nieprawidłowy stan.
    • ClientNoAction wymusza, aby EF Core nie sprawdzał zależnych obiektów przed wysłaniem ich do bazy danych, więc w tym przypadku baza danych generuje wyjątek, który jest następnie owinięty przez DbUpdateException w SaveChanges.
    • SetNull jest odrzucany podczas tworzenia bazy danych, ponieważ kolumna klucza obcego nie może zawierać wartości null.
  • Ponieważ elementy podrzędne są ładowane, są one zawsze usuwane przez EF Core i nigdy nie pozostawiane do usunięcia przez bazę danych.

Wymagana relacja z zależnościami/dziećmi nie została załadowana.

UsuńBehavior Usuwanie podmiotu głównego/nadrzędnego elementu Na odłączenie od źródła/podmiotu nadrzędnego
Kaskada Zależności usunięte przez bazę danych N/A
Ograniczać DbUpdateException N/A
Brak działania DbUpdateException N/A
SetNull SqlException o tworzeniu bazy danych N/A
ClientSetNull DbUpdateException N/A
ClientCascade DbUpdateException N/A
ClientNoAction DbUpdateException N/A

Notatki:

  • Zerwanie relacji nie jest tutaj prawidłowe, ponieważ zależności/elementy podrzędne nie są ładowane.
  • Wartością domyślną dla wymaganych relacji jest następująca: Cascade.
  • Zastosowanie metody innej niż usuwanie kaskadowe dla wymaganych relacji spowoduje zgłoszenie wyjątku w momencie wywołania funkcji SaveChanges.
    • Zazwyczaj jest to DbUpdateException, ponieważ zależności/dzieci nie są ładowane, dlatego nieprawidłowy stan można wykryć tylko przy użyciu bazy danych. Funkcja SaveChanges następnie opakowuje wyjątek bazy danych w elemencie DbUpdateException.
    • SetNull jest odrzucany podczas tworzenia bazy danych, ponieważ kolumna klucza obcego nie może zawierać wartości null.

Opcjonalna relacja z załadowanymi zależnościami/dzieckiem

UsuńBehavior Usuwanie podmiotu głównego/nadrzędnego elementu Na odłączenie od źródła/podmiotu nadrzędnego
Kaskada Zależności usunięte przez program EF Core Zależności usunięte przez program EF Core
Ograniczać Zależne zestawy FKs ustawione na wartość null przez program EF Core Zależne zestawy FKs ustawione na wartość null przez program EF Core
Brak działania Zależne zestawy FKs ustawione na wartość null przez program EF Core Zależne zestawy FKs ustawione na wartość null przez program EF Core
SetNull Zależne zestawy FKs ustawione na wartość null przez program EF Core Zależne zestawy FKs ustawione na wartość null przez program EF Core
ClientSetNull Zależne zestawy FKs ustawione na wartość null przez program EF Core Zależne zestawy FKs ustawione na wartość null przez program EF Core
ClientCascade Zależności usunięte przez program EF Core Zależności usunięte przez program EF Core
ClientNoAction DbUpdateException Zależne zestawy FKs ustawione na wartość null przez program EF Core

Notatki:

  • Wartość domyślna dla relacji opcjonalnych, takich jak ta, to ClientSetNull.
  • Zależności/dzieci nigdy nie są usuwane, chyba że Cascade lub ClientCascade są skonfigurowane.
  • Wszystkie inne wartości powodują ustawienie zależnych zestawów FKs na wartość null przez program EF Core...
    • ... z wyjątkiem ClientNoAction, które nakazuje EF Core, aby nie zmieniał kluczy obcych dzieci, gdy podmiot nadrzędny jest usuwany. W związku z tym baza danych zgłasza wyjątek, który funkcja SaveChanges zawija jako DbUpdateException.

Opcjonalna relacja z osobami zależnymi/dziećmi nie załadowana

UsuńBehavior Usuwanie podmiotu głównego/nadrzędnego elementu Na odłączenie od źródła/podmiotu nadrzędnego
Kaskada Zależności usunięte przez bazę danych N/A
Ograniczać DbUpdateException N/A
Brak działania DbUpdateException N/A
SetNull Zależne zestawy FKs ustawione na wartość null przez bazę danych N/A
ClientSetNull DbUpdateException N/A
ClientCascade DbUpdateException N/A
ClientNoAction DbUpdateException N/A

Notatki:

  • Zerwanie relacji nie jest tutaj prawidłowe, ponieważ zależności/elementy podrzędne nie są ładowane.
  • Wartość domyślna dla relacji opcjonalnych, takich jak ta, to ClientSetNull.
  • Dzieci będące na utrzymaniu muszą zostać załadowane, aby uniknąć wyjątku w bazie danych, chyba że baza danych została skonfigurowana do kaskadowego usuwania lub ustawiania wartości null.