하위 삭제
EF Core(Entity Framework Core)는 외래 키를 사용하여 관계를 나타냅니다. 외래 키가 있는 엔터티는 관계에서 자식 또는 종속 엔터티입니다. 해당 엔터티의 외래 키 값은 관련 보안 주체/부모 엔터티의 기본 키 값(또는 대체 키 값)과 일치해야 합니다.
보안 주체/부모 엔터티가 삭제되면 종속 항목/자식의 외래 키 값이 더 이상 ‘모든’ 보안 주체.부모의 기본 또는 대체 키와 일치하지 않습니다. 이는 잘못된 상태이며 대부분 데이터베이스에서 참조 제약 조건 위반을 초래합니다.
해당 참조 제약 조건 위반을 방지하는 두 가지 옵션이 있습니다.
- FK 값을 null로 설정
- 종속/자식 엔터티도 삭제
첫 번째 옵션은 외래 키 속성(및 해당 속성이 매핑되는 데이터베이스 열)이 null을 허용해야 하는 선택적 관계에만 유효합니다.
두 번째 옵션은 모든 종류의 관계에 유효하며 “하위 삭제”라고 합니다.
팁
이 문서에서는 데이터베이스 업데이트 관점에서 하위 삭제(및 고아 삭제)를 설명합니다. 문서에서는 EF Core의 변경 내용 추적 및 외래 키 및 탐색 변경에 도입된 개념을 많이 사용합니다. 여기에서 자료를 살펴보기 전에 관련 개념을 완전히 이해해야 합니다.
팁
GitHub에서 샘플 코드를 다운로드하여 이 문서의 모든 코드를 실행하고 디버그할 수 있습니다.
계단식 배열 동작이 발생하는 경우
종속/자식 엔터티를 현재 보안 주체/부모 엔터티와 더 이상 연결할 수 없는 경우 하위 삭제가 필요합니다. 해당 문제는 보안 주체/부모가 삭제되거나 보안 주체/부모가 존재하지만 종속 항목/자식이 더 이상 연결되지 않기 때문에 발생할 수 있습니다.
보안 주체/부모 삭제
종속 항목/자식인 Post
와 관계에서 Blog
가 보안 주체/부모인 간단한 모델을 살펴봅니다. 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; }
}
규칙에 따라 Post.BlogId
외래 키 속성이 null을 허용하지 않기 때문에 이 관계는 필수로 구성됩니다. 필수 관계는 기본적으로 하위 삭제를 사용하도록 구성됩니다. 관계 모델링에 관한 자세한 내용은 관계를 참조하세요.
블로그를 삭제하면 모든 게시물이 하위 삭제됩니다. 예를 들면 다음과 같습니다.
using var context = new BlogsContext();
var blog = context.Blogs.OrderBy(e => e.Name).Include(e => e.Posts).First();
context.Remove(blog);
context.SaveChanges();
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 = context.Blogs.OrderBy(e => e.Name).Include(e => e.Posts).First();
foreach (var post in blog.Posts)
{
post.Blog = null;
}
context.SaveChanges();
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();
어느 경우에나 결과는 동일합니다. 블로그는 삭제되지 않지만 블로그와 더 이상 연결되지 않는 게시물은 삭제됩니다.
-- 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.CascadeDeleteTiming 및 ChangeTracker.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 = context.Blogs.OrderBy(e => e.Name).First();
context.Remove(blog);
context.SaveChanges();
게시물에 대한 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): 테이블 ‘Posts’에 FOREIGN KEY 제약 조건 ‘FK_Posts_Person_AuthorId’를 사용하면 경로가 순환하거나 여러 경로가 중첩될 수 있습니다. ON DELETE NO ACTION 또는 ON UPDATE NO ACTION을 지정하거나 다른 FOREIGN KEY 제약 조건을 수정하십시오.
해당 상황을 처리하는 방법에는 두 가지가 있습니다.
- 하위 삭제되지 않도록 하나 이상의 관계를 변경합니다.
- 하위 삭제 중 하나 이상을 사용하지 않고 데이터베이스를 구성한 다음, 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 = context.People.Single(e => e.Name == "ajcvickers");
var blog = context.Blogs.Single(e => e.Owner == owner);
context.Remove(owner);
context.SaveChanges();
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 = context.People.Single(e => e.Name == "ajcvickers");
context.Remove(owner);
context.SaveChanges();
데이터베이스의 외래 키 제약 조건 위반으로 인해 예외가 throw됩니다.
Microsoft.Data.SqlClient.SqlException: DELETE 문이 REFERENCE 제약 조건 “FK_Blogs_People_OwnerId”와 충돌합니다. 데이터베이스 “Scratch”, 테이블 “dbo.Blogs”, 열 ‘OwnerId’에서 충돌이 발생했습니다. 문이 종료되었습니다.
계단식 배열 null
선택적 관계에서는 null 허용 외래 키 속성이 null 허용 데이터베이스 열에 매핑됩니다. 즉, 현재 보안 주체/부모가 삭제되거나 종속 항목/자식에서 단절되는 경우 외래 키 값을 null로 설정할 수 있습니다.
계단식 배열 동작이 발생하는 경우의 예제를 다시 살펴보겠습니다. 하지만 이번에는 null 허용 Post.BlogId
외래 키 속성으로 선택적 관계를 나타냅니다.
public int? BlogId { get; set; }
해당 외래 키 속성은 관련된 블로그가 삭제될 때 각 게시물에 대해 null로 설정됩니다. 예를 들어 이전과 동일한 해당 코드는:
using var context = new BlogsContext();
var blog = context.Blogs.OrderBy(e => e.Name).Include(e => e.Posts).First();
context.Remove(blog);
context.SaveChanges();
이제 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 = context.Blogs.OrderBy(e => e.Name).Include(e => e.Posts).First();
foreach (var post in blog.Posts)
{
post.Blog = null;
}
context.SaveChanges();
또는
using var context = new BlogsContext();
var blog = context.Blogs.OrderBy(e => e.Name).Include(e => e.Posts).First();
blog.Posts.Clear();
context.SaveChanges();
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 구성에 관한 자세한 내용은 다음 섹션을 참조하세요.
계단식 배열 동작 구성
팁
진행하기 전에 먼저 위의 섹션을 읽어 보아야 합니다. 위의 자료를 이해하지 못했다면 구성 옵션이 이해되지 않을 수 있습니다.
계단식 배열 동작은 OnModelCreating에서 OnDelete 메서드를 사용하여 관계별로 구성됩니다. 예를 들면 다음과 같습니다.
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 마이그레이션 또는 EnsureCreated에서 만든 외래 키 제약 조건에 따른 각 OnDelete
값의 결과를 보여 줍니다.
DeleteBehavior | 데이터베이스 스키마에 미치는 영향 |
---|---|
계단식 배열 | ON DELETE CASCADE |
제한 | ON DELETE RESTRICT |
NoAction | 데이터베이스 기본 |
SetNull | ON DELETE SET NULL |
ClientSetNull | 데이터베이스 기본 |
ClientCascade | 데이터베이스 기본 |
ClientNoAction | 데이터베이스 기본 |
관계형 데이터베이스에서 ON DELETE NO ACTION
(데이터베이스 기본값) 및 ON DELETE RESTRICT
의 동작은 일반적으로 동일하거나 매우 유사합니다. NO ACTION
의 가능한 의미와는 다르게 해당 옵션은 둘 다 참조 제약 조건을 적용합니다. 한 가지 차이점은 데이터베이스가 제약 조건을 확인할 ‘때’입니다. ON DELETE NO ACTION
과 ON DELETE RESTRICT
간 특정 차이점에 관해서는 데이터베이스 설명서를 참조하세요.
SQL Server에서 ON DELETE RESTRICT
를 지원하지 않으므로 ON DELETE NO ACTION
이 대신 사용됩니다.
데이터베이스에서 계단식 배열 동작을 초래하는 유일한 값은 Cascade
및 SetNull
입니다. 다른 모든 값은 변경 내용을 계단식으로 처리하지 않도록 데이터베이스를 구성합니다.
SaveChanges 동작에 미치는 영향
다음 섹션의 표에서는 보안 주체/부모가 삭제되거나 종속/자식 엔터티에 대한 관계가 단절되는 경우 종속/자식 엔터티에 수행되는 작업을 다룹니다. 각 표는 다음 중 하나를 다룹니다.
- 선택적(null 허용 FK) 및 필수(null을 허용하지 않는 FK) 관계
- DbContext에서 종속 항목/자식을 로드하고 추적하는 경우 및 종속 항목/자식이 데이터베이스에만 있는 경우
로드되는 종속 항목/자식과 필수 관계
DeleteBehavior | 보안 주체/부모 삭제 시 | 보안 주체/부모에서 단절 시 |
---|---|---|
계단식 배열 | EF Core에서 삭제된 종속 항목 | EF Core에서 삭제된 종속 항목 |
제한 | InvalidOperationException |
InvalidOperationException |
NoAction | InvalidOperationException |
InvalidOperationException |
SetNull | 데이터베이스를 만들 때 SqlException |
데이터베이스를 만들 때 SqlException |
ClientSetNull | InvalidOperationException |
InvalidOperationException |
ClientCascade | EF Core에서 삭제된 종속 항목 | EF Core에서 삭제된 종속 항목 |
ClientNoAction | DbUpdateException |
InvalidOperationException |
참고:
- 이와 같은 필수 관계의 기본값은
Cascade
입니다. - 필수 관계에 하위 삭제 이외의 작업을 사용하면 SaveChanges가 호출될 때 예외가 발생합니다.
- 일반적으로 해당 예외는 로드된 자식/종속 항목에서 잘못된 상태가 검색되기 때문에 EF Core에서 발생하는
InvalidOperationException
입니다. ClientNoAction
은 수정 종속 항목을 데이터베이스에 보내기 전에 EF Core가 수정 종속 항목을 강제로 확인하지 않도록 하므로, 이 경우 데이터베이스는 예외를 throw하고 이후 해당 예외는 SaveChanges에 의해DbUpdateException
으로 래핑됩니다.SetNull
은 외래 키 열이 null을 허용하지 않기 때문에 데이터베이스를 만들 때가 거부됩니다.
- 일반적으로 해당 예외는 로드된 자식/종속 항목에서 잘못된 상태가 검색되기 때문에 EF Core에서 발생하는
- 종속 항목/자식은 로드되므로 항상 EF Core에 의해 삭제되며 데이터베이스가 삭제될 때 남아 있지 않습니다.
로드되지 않는 종속 항목/자식과 필수 관계
DeleteBehavior | 보안 주체/부모 삭제 시 | 보안 주체/부모에서 단절 시 |
---|---|---|
계단식 배열 | 데이터베이스에서 삭제된 종속 항목 | N/A |
제한 | DbUpdateException |
N/A |
NoAction | DbUpdateException |
N/A |
SetNull | 데이터베이스를 만들 때 SqlException |
N/A |
ClientSetNull | DbUpdateException |
N/A |
ClientCascade | DbUpdateException |
N/A |
ClientNoAction | DbUpdateException |
N/A |
참고:
- 종속 항목/자식이 로드되지 않기 때문에 여기서는 관계 단절이 유효하지 않습니다.
- 이와 같은 필수 관계의 기본값은
Cascade
입니다. - 필수 관계에 하위 삭제 이외의 작업을 사용하면 SaveChanges가 호출될 때 예외가 발생합니다.
- 일반적으로 해당 예외는 종속 항목/자식이 로드되지 않을 뿐 아니라 데이터베이스만 잘못된 상태를 검색할 수 있기 때문에
DbUpdateException
입니다. 이후 SaveChanges는 데이터베이스 예외를DbUpdateException
으로 래핑합니다. SetNull
은 외래 키 열이 null을 허용하지 않기 때문에 데이터베이스를 만들 때가 거부됩니다.
- 일반적으로 해당 예외는 종속 항목/자식이 로드되지 않을 뿐 아니라 데이터베이스만 잘못된 상태를 검색할 수 있기 때문에
로드되는 종속 항목/자식과 선택적 관계
DeleteBehavior | 보안 주체/부모 삭제 시 | 보안 주체/부모에서 단절 시 |
---|---|---|
계단식 배열 | EF Core에서 삭제된 종속 항목 | EF Core에서 삭제된 종속 항목 |
제한 | EF Core에서 null로 설정된 종속 FK | EF Core에서 null로 설정된 종속 FK |
NoAction | 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에서 삭제된 종속 항목 |
ClientNoAction | DbUpdateException |
EF Core에서 null로 설정된 종속 FK |
참고:
- 이와 같은 선택적 관계의 기본값은
ClientSetNull
입니다. Cascade
또는ClientCascade
가 구성되지 않는 경우에는 종속 항목/자식이 삭제되지 않습니다.- 다른 모든 값을 사용하면 EF Core에서 종속 FK를 null로 설정합니다.
- ...단,
ClientNoAction
은 보안 주체/부모가 삭제될 때 종속 항목/자식의 외래 키를 변경하지 않도록 EF Core에 알립니다. 따라서 데이터베이스는 SaveChanges에 의해DbUpdateException
으로 래핑되는 예외를 throw합니다.
- ...단,
로드되지 않는 종속 항목/자식과 선택적 관계
DeleteBehavior | 보안 주체/부모 삭제 시 | 보안 주체/부모에서 단절 시 |
---|---|---|
계단식 배열 | 데이터베이스에서 삭제된 종속 항목 | N/A |
제한 | DbUpdateException |
N/A |
NoAction | DbUpdateException |
N/A |
SetNull | 데이터베이스에서 null로 설정된 종속 FK | N/A |
ClientSetNull | DbUpdateException |
N/A |
ClientCascade | DbUpdateException |
N/A |
ClientNoAction | DbUpdateException |
N/A |
참고:
- 종속 항목/자식이 로드되지 않기 때문에 여기서는 관계 단절이 유효하지 않습니다.
- 이와 같은 선택적 관계의 기본값은
ClientSetNull
입니다. - 데이터베이스가 삭제 또는 null을 계단식으로 처리하도록 구성되는 경우가 아니면 데이터베이스 예외를 방지하기 위해 종속 항목/자식을 로드해야 합니다.
.NET