다음을 통해 공유


Cascade 삭제

EF Core(Entity Framework Core)는 외장 키를 사용하는 관계를 나타냅니다. 외래 키가 있는 엔터티는 관계의 자식 또는 종속 엔터티입니다. 이 엔터티의 외래 키 값은 관련 보안 주체/부모 엔터티의 기본 키 값(또는 대체 키 값)과 일치해야 합니다.

기본/부모 엔터티가 삭제되면, 종속/자식의 외래 키 값이 더 이상 어느 주체/부모 엔터티의 기본 또는 대체 키와도 일치하지 않게 됩니다. 잘못된 상태이며 대부분의 데이터베이스에서 참조 제약 조건 위반이 발생합니다.

이 참조 제약 조건 위반을 방지하는 두 가지 옵션이 있습니다.

  1. FK 값을 null로 설정
  2. 종속/자식 엔터티도 삭제합니다.

첫 번째 옵션은 외래 키 속성(및 매핑된 데이터베이스 열)을 null 허용해야 하는 선택적 관계에만 유효합니다.

두 번째 옵션은 모든 종류의 관계에 유효하며 "cascade delete"라고 합니다.

팁 (조언)

이 문서에서는 데이터베이스를 업데이트하는 관점에서 연속 삭제와 고아 삭제를 설명합니다. EF Core의 변경 내용 추적외래 키 및 탐색 변경에 도입된 개념을 많이 사용합니다. 여기에서 자료를 다루기 전에 이러한 개념을 완전히 이해해야 합니다.

팁 (조언)

GitHub에서 샘플 코드를 다운로드하여 이 문서의 모든 코드를 실행하고 디버그할 수 있습니다.

연속 동작이 발생하는 경우

종속/자식 엔터티를 현재 주체/부모와 더 이상 연결할 수 없는 경우 연쇄 삭제가 필요합니다. 이는 보안 주체/부모가 삭제되었거나 보안 주체/부모가 여전히 존재하지만 종속/자식이 더 이상 연결되지 않은 경우에 발생할 수 있기 때문에 발생할 수 있습니다.

보안 주체/부모 삭제

간단한 모델에서 Blog이 관계의 주체/부모이고 Post이 종속/자식인 경우를 고려합니다. Post.BlogId 는 외래 키 속성이며, 이 값은 게시물이 Blog.Id 속한 블로그의 기본 키와 일치해야 합니다.

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

규칙에 따라 외래 키 속성은 null을 허용하지 않으므로 이 관계는 필수 Post.BlogId 로 구성됩니다. 필수 관계는 기본적으로 연계 삭제를 사용하도록 구성됩니다. 관계 모델링에 대한 자세한 내용은 관계를 참조하세요.

블로그를 삭제하면 모든 게시물이 연쇄적으로 삭제됩니다. 다음은 그 예입니다.

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

SaveChanges는 SQL Server를 예로 사용하여 다음 SQL을 생성합니다.

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

관계 끊기

블로그를 삭제하는 대신 각 게시물과 블로그 간의 관계를 끊을 수 있습니다. 이 작업은 각 게시물에 대한 참조 탐색 Post.Blog 을 null로 설정하여 수행할 수 있습니다.

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

각 게시물을 컬렉션 탐색에서 삭제하여 관계를 끊을 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();

두 경우 모두 결과는 동일합니다. 블로그는 삭제되지 않지만 더 이상 블로그와 연결되지 않은 게시물은 삭제됩니다.

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

더 이상 주체/종속과 연결되지 않은 엔터티를 삭제하는 것을 '고아 삭제'라고 합니다.

팁 (조언)

계단식 삭제와 고아 삭제는 밀접하게 관련되어 있습니다. 둘 다 필수 주요/부모와의 관계가 끊어지면 종속/자식 엔터티를 삭제합니다. 연계 삭제의 경우, 주체/부모가 삭제되면서 이 분리가 발생합니다. 고아 엔터티의 경우, 주체/부모 엔터티는 여전히 존재하지만 더 이상 종속/자식 엔터티와 연관되어 있지 않습니다.

연속 동작이 발생하는 위치

연계 동작은 다음을 적용할 수 있습니다.

  • 현재 추적 중인 엔티티 DbContext
  • 컨텍스트에 로드되지 않은 데이터베이스 내의 엔터티

추적된 엔터티의 연쇄 삭제

EF Core는 항상 구성된 연계 동작을 추적된 엔터티에 적용합니다. 즉, 애플리케이션이 위의 예제와 같이 모든 관련 종속/자식 엔터티를 DbContext에 로드하는 경우 데이터베이스 구성 방법에 관계없이 연속 동작이 올바르게 적용됩니다.

팁 (조언)

추적된 엔터티에 대한 연계 동작이 발생하는 정확한 타이밍은 다음을 사용하여 ChangeTracker.CascadeDeleteTimingChangeTracker.DeleteOrphansTiming제어할 수 있습니다. 자세한 내용은 외래키 및 탐색 변경을 참조하세요.

데이터베이스의 계단식 삭제

또한 많은 데이터베이스 시스템은 데이터베이스에서 엔터티가 삭제될 때 트리거되는 연속 동작을 제공합니다. EF Core는 EnsureCreated 또는 EF Core 마이그레이션을 사용하여 데이터베이스를 생성할 때 EF Core 모델의 계단식 삭제 동작에 따라 이러한 동작을 구성합니다. 예를 들어 위의 모델을 사용하면 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
);

블로그와 게시물 간의 관계를 정의하는 외래 키 제약 조건이 ON DELETE CASCADE로 구성되어 있음을 주목하세요.

데이터베이스가 이와 같이 구성된 경우 먼저 게시물을 로드하지 않고 블로그를 삭제할 수 있으며 데이터베이스는 해당 블로그와 관련된 모든 게시물을 삭제합니다. 다음은 그 예입니다.

using var context = new BlogsContext();

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

context.Remove(blog);

await context.SaveChangesAsync();

Include가 게시물에 없으므로 게시물이 로드되지 않습니다. 이 경우 SaveChanges는 추적 중인 유일한 엔터티이므로 블로그만 삭제합니다.

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

데이터베이스의 외래 키 제약 조건이 연속 삭제에 대해 구성되지 않은 경우 예외가 발생합니다. 그러나 이 경우 게시물은 생성될 때 구성 ON DELETE CASCADE 되었으므로 데이터베이스에서 삭제됩니다.

비고

데이터베이스는 일반적으로 고아 데이터를 자동으로 삭제할 수 있는 방법이 없습니다. EF Core는 외래 키뿐만 아니라 탐색 기능을 사용하여 관계를 나타내지만, 데이터베이스에는 외래 키만 있고 탐색 기능은 없기 때문입니다. 즉, 일반적으로 양쪽을 DbContext에 로드하지 않고는 관계를 끊을 수 없습니다.

비고

EF Core 메모리 내 데이터베이스는 현재 데이터베이스에서 연속 삭제를 지원하지 않습니다.

경고

엔터티를 일시 삭제할 때 데이터베이스에서 계단식 삭제를 구성하지 마세요. 이로 인해 엔터티가 소프트 삭제되지 않고 실수로 실제로 삭제될 수 있습니다.

데이터베이스 연계 제한 사항

일부 데이터베이스( 특히 SQL Server)에는 주기를 형성하는 계단식 동작에 대한 제한 사항이 있습니다. 예를 들어 다음 모델을 고려합니다.

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

이 모델에는 세 개의 관계가 있으며, 모두 필수이므로 규칙에 따라 삭제를 연계하도록 구성됩니다.

  • 블로그를 삭제하면 관련 게시물이 모두 삭제됩니다.
  • 게시물 작성자를 삭제하면 만든 게시물이 연속 삭제됩니다.
  • 블로그 소유자를 삭제하면 블로그가 연속 삭제됩니다.

이는 모두 합리적이지만(블로그 관리 정책이 조금 가혹하긴 하지만) 계단식 처리가 구성된 SQL Server 데이터베이스를 만들려고 시도할 경우, 결과적으로 다음과 같은 예외가 발생합니다.

Microsoft.Data.SqlClient.SqlException(0x80131904): '게시물' 테이블에 FOREIGN KEY 제약 조건 'FK_Posts_Person_AuthorId'을 도입하면 주기 또는 여러 계단식 경로가 발생할 수 있습니다. ON DELETE NO ACTION 또는 ON UPDATE NO ACTION을 지정하거나 다른 FOREIGN KEY 제약 조건을 수정하십시오.

이 상황을 처리하는 방법에는 두 가지가 있습니다.

  1. 하나 이상의 관계에서 연쇄 삭제가 발생하지 않도록 변경합니다.
  2. 이러한 연속 삭제를 하나 이상 수행하지 않고 데이터베이스를 구성한 다음, EF Core에서 연속 동작을 수행할 수 있도록 모든 종속 엔터티가 로드되었는지 확인합니다.

예제에서 첫 번째 접근 방식을 사용하면 nullable 외래 키 속성을 제공하여 게시물-블로그 관계를 선택적일 수 있습니다.

public int? BlogId { get; set; }

선택적 관계를 사용하면 게시물이 블로그 없이 존재할 수 있습니다. 즉, 계단식 삭제는 기본적으로 더 이상 구성되지 않습니다. 즉, 연속 작업에는 더 이상 주기가 없으며 SQL Server에서 오류 없이 데이터베이스를 만들 수 있습니다.

대신 두 번째 방법을 사용하면 연속 삭제에 필요한 블로그 소유자 관계를 유지하고 구성할 수 있지만 이 구성은 데이터베이스가 아닌 추적된 엔터티에만 적용되도록 할 수 있습니다.

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

이제 개인과 자신이 소유한 블로그를 모두 로드한 다음 해당 사용자를 삭제하면 어떻게 되나요?

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는 소유자 삭제를 연계하여 블로그도 삭제합니다.

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

그러나 소유자가 삭제될 때 블로그가 로드되지 않는 경우:

using var context = new BlogsContext();

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

context.Remove(owner);

await context.SaveChangesAsync();

그런 다음 데이터베이스의 외래 키 제약 조건 위반으로 인해 예외가 발생합니다.

Microsoft.Data.SqlClient.SqlException: DELETE 문이 REFERENCE 제약 조건 "FK_Blogs_People_OwnerId"과 충돌했습니다. 데이터베이스 "Scratch", 테이블 "dbo.Blogs", 열 'OwnerId'에서 충돌이 발생했습니다. 진술이 종료되었습니다.

연쇄 null

선택적 관계에는 데이터베이스의 nullable 열에 매핑된 nullable 외래 키 속성이 포함됩니다. 즉, 현재 주요 개체/부모가 삭제되거나 종속/자식에서 분리될 때 외래 키 값을 null로 설정할 수 있습니다.

연계 동작이 발생하는 경우의 예제를 다시 살펴보겠습니다. 하지만 이번에는 nullable Post.BlogId 외래 키 속성으로 표시되는 선택적 관계와 함께 다음을 살펴보겠습니다.

public int? BlogId { get; set; }

이 외래 키 속성은 관련 블로그가 삭제될 때 각 게시물에 대해 null로 설정됩니다. 예를 들어 이 코드는 이전과 동일합니다.

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

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

마찬가지로 위의 예제 중 하나를 사용하여 관계가 끊어지면 다음과 같습니다.

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

또는:

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

그런 다음 SaveChanges가 호출되면 게시물이 null 외래 키 값으로 업데이트됩니다.

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

이 변경 될 때 EF Core가 외신 키 및 탐색을 관리하는 방법에 대한 자세한 내용은 외신 키 및 탐색 변경을 참조하세요.

비고

이와 같은 관계의 수정은 2008년 첫 번째 버전 이후 Entity Framework의 기본 동작이었습니다. EF Core 이전에는 이름이 없었고 변경할 수 없었습니다. 이제 다음 섹션에 설명된 대로 ClientSetNull 알려져 있습니다.

선택적 관계의 주체/부모가 삭제될 때 이와 같은 null을 연계하도록 데이터베이스를 구성할 수도 있습니다. 그러나 이는 데이터베이스에서 연속 삭제를 사용하는 것보다 훨씬 덜 일반적입니다. 데이터베이스에서 연속 삭제 및 연속 null을 동시에 사용하면 SQL Server를 사용할 때 거의 항상 관계 주기가 발생합니다. 연계 null을 구성하는 방법에 대한 자세한 내용은 다음 섹션을 참조하세요.

연속 동작 구성

팁 (조언)

여기에 오기 전에 위의 섹션을 읽어야합니다. 이전 자료를 이해하지 못하면 구성 옵션이 의미가 없을 수 있습니다.

연계 동작은 OnDelete 메서드를 사용하여 OnModelCreating에서 관계별로 구성됩니다. 다음은 그 예입니다.

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

엔터티 형식 간의 관계를 구성하는 방법에 대한 자세한 내용은 관계를 참조하세요.

OnDelete 는 솔직히 혼란스러운 DeleteBehavior 열거형의 값을 허용합니다. 이 열거형은 추적된 엔터티에서 EF Core의 동작과 EF를 사용하여 스키마를 만들 때 데이터베이스에서 계단식 삭제의 구성을 모두 정의합니다.

데이터베이스 스키마에 미치는 영향

다음 표에서는 EF Core 마이그레이션 또는 OnDelete에 의해 생성된 외래 키 제약 조건에 대한 각 EnsureCreated 값의 결과를 보여 줍니다.

삭제 동작 데이터베이스 스키마에 미치는 영향
폭포 ON DELETE CASCADE (삭제 시 자동 연쇄 삭제)
제한 삭제 시 제한 (ON DELETE RESTRICT)
안전 조치 없음 데이터베이스 기본값
SetNull 삭제 시 NULL로 설정
클라이언트세트널 (ClientSetNull) 데이터베이스 기본값
ClientCascade 데이터베이스 기본값
클라이언트작업안함 데이터베이스 기본값

(데이터베이스 기본값) 및 ON DELETE NO ACTION 관계형 데이터베이스의 ON DELETE RESTRICT 동작은 일반적으로 동일하거나 매우 유사합니다. 암시할 수 있는 내용 NO ACTION 에도 불구하고 이러한 두 옵션으로 인해 참조 제약 조건이 적용됩니다. 차이점은 데이터베이스가 제약 조건을 확인하는 경우 입니다. 데이터베이스 시스템에서 ON DELETE NO ACTIONON DELETE RESTRICT 간의 특정 차이점을 확인하려면 데이터베이스 설명서를 참조하십시오.

SQL Server는 지원하지 ON DELETE RESTRICT않으므로 ON DELETE NO ACTION 대신 사용됩니다.

데이터베이스에서 연속 동작을 발생시키는 유일한 값은 다음과 Cascade같습니다SetNull. 다른 모든 값은 변경 내용을 연계하지 않도록 데이터베이스를 구성합니다.

SaveChanges 동작에 미치는 영향

다음 섹션의 표에서는 주체/부모가 삭제되거나 종속/자식 엔터티와의 관계가 끊어질 때 종속/자식 엔터티에 어떤 일이 발생하는지를 설명합니다. 각 테이블은 다음 중 하나를 다룹니다.

  • 선택적 관계(널 허용 FK) 및 필수 관계(널 비허용 FK)
  • 종속/자식이 DbContext에 의해 로드 및 추적되는 경우 및 데이터베이스에만 있는 경우

로드된 종속/자식과의 필수 관계

삭제 동작 주체/부모를 삭제할 때 보안 주체/부모에서 분리 시
폭포 EF Core에서 삭제한 종속성 EF Core에서 삭제한 종속성
제한 InvalidOperationException InvalidOperationException
안전 조치 없음 InvalidOperationException InvalidOperationException
SetNull SqlException 데이터베이스를 만들 때 SqlException 데이터베이스를 만들 때
ClientSetNull InvalidOperationException InvalidOperationException
ClientCascade EF Core에서 삭제한 종속성 EF Core에서 삭제한 종속성
클라이언트작업안함 DbUpdateException InvalidOperationException

노트:

  • 이와 같은 필수 관계의 기본값은 .입니다 Cascade.
  • 필요한 관계에 대해 계단식 삭제 이외의 항목을 사용하면 SaveChanges가 호출될 때 예외가 발생합니다.
    • 일반적으로 InvalidOperationException 로드된 자식/종속성에서 잘못된 상태가 검색되기 때문에 EF Core에서 반환됩니다.
    • ClientNoAction는 EF Core에 강제로 수정 종속 항목을 데이터베이스로 보내기 전에 검사하지 않도록 합니다. 따라서 이 경우 데이터베이스가 예외를 발생시키고, 그 예외는 SaveChanges에서 DbUpdateException로 래핑됩니다.
    • SetNull 는 외래 키 열이 null을 허용하지 않으므로 데이터베이스를 만들 때 거부됩니다.
  • 종속 항목/자식 항목이 로드되면 EF Core에서 항상 삭제되며 데이터베이스가 삭제하도록 남겨두지 않습니다.

종속/자식과의 필수 관계가 로드되지 않음

삭제 동작 주체/부모를 삭제할 때 보안 주체/부모에서 분리 시
폭포 데이터베이스에서 삭제된 종속성 해당 없음(N/A)
제한 DbUpdateException 해당 없음(N/A)
안전 조치 없음 DbUpdateException 해당 없음(N/A)
SetNull SqlException 데이터베이스를 만들 때 해당 없음(N/A)
ClientSetNull DbUpdateException 해당 없음(N/A)
ClientCascade DbUpdateException 해당 없음(N/A)
클라이언트작업안함 DbUpdateException 해당 없음(N/A)

노트:

  • 여기서는 종속/자식이 로드되지 않으므로 관계를 끊을 수 없습니다.
  • 이와 같은 필수 관계의 기본값은 .입니다 Cascade.
  • 필요한 관계에 대해 계단식 삭제 이외의 항목을 사용하면 SaveChanges가 호출될 때 예외가 발생합니다.
    • 일반적으로 이는 DbUpdateException 종속/자식이 로드되지 않으므로 데이터베이스에서만 잘못된 상태를 검색할 수 있기 때문입니다. SaveChanges가 데이터베이스 예외를 DbUpdateException로 래핑합니다.
    • SetNull 는 외래 키 열이 null을 허용하지 않으므로 데이터베이스를 만들 때 거부됩니다.

부양 가족/자녀와의 선택적 관계 로드됨

삭제 동작 주체/부모를 삭제할 때 보안 주체/부모에서 분리 시
폭포 EF Core에서 삭제한 종속성 EF Core에서 삭제한 종속성
제한 EF Core에서 Null로 설정된 종속 FK EF Core에서 Null로 설정된 종속 FK
안전 조치 없음 EF Core에서 Null로 설정된 종속 FK EF Core에서 Null로 설정된 종속 FK
SetNull EF Core에서 Null로 설정된 종속 FK EF Core에서 Null로 설정된 종속 FK
ClientSetNull EF Core에서 Null로 설정된 종속 FK EF Core에서 Null로 설정된 종속 FK
ClientCascade EF Core에서 삭제한 종속성 EF Core에서 삭제한 종속성
클라이언트작업안함 DbUpdateException EF Core에서 Null로 설정된 종속 FK

노트:

  • 이와 같은 선택적 관계의 기본값은 .입니다 ClientSetNull.
  • 종속자나 자식은 Cascade 또는 ClientCascade이 구성된 경우가 아니면 삭제되지 않습니다.
  • 다른 모든 값으로 인해 종속 FK가 EF Core에서 null로 설정됩니다...
    • ... 는 보안 주체/부모가 삭제될 때 종속/자식의 외장 키를 건드리지 않도록 EF Core에 지시하는 것을 제외 ClientNoAction 합니다. 따라서 데이터베이스는 SaveChanges에 의해 DbUpdateException로 래핑된 예외를 발생시킵니다.

로드되지 않은 종속/자식과의 선택적 관계

삭제 동작 주체/부모를 삭제할 때 보안 주체/부모에서 분리 시
폭포 데이터베이스에서 삭제된 종속성 해당 없음(N/A)
제한 DbUpdateException 해당 없음(N/A)
안전 조치 없음 DbUpdateException 해당 없음(N/A)
SetNull 데이터베이스별로 null로 설정된 종속 FK 해당 없음(N/A)
ClientSetNull DbUpdateException 해당 없음(N/A)
ClientCascade DbUpdateException 해당 없음(N/A)
클라이언트작업안함 DbUpdateException 해당 없음(N/A)

노트:

  • 여기서는 종속/자식이 로드되지 않으므로 관계를 끊을 수 없습니다.
  • 이와 같은 선택적 관계의 기본값은 .입니다 ClientSetNull.
  • 데이터베이스가 삭제 또는 null을 연쇄적으로 처리하도록 구성되지 않은 한 데이터베이스 예외를 방지하려면 종속 객체나 자식을 로드해야 합니다.