키 없는 엔터티 형식

참고

이 기능은 쿼리 유형 이름 아래에 추가 되었습니다. 나중에 키가 없는 엔터티 형식으로 이름이 변경 되었습니다. [Keyless]데이터 주석은 EFCore 5.0에서 사용할 수 있습니다.

일반 엔터티 형식 외에도 EF Core 모델에는 키 값이 포함 되지 않은 데이터에 대 한 데이터베이스 쿼리를 수행 하는 데 사용할 수 있는 키가 없는 엔터티 형식이포함 될 수 있습니다.

키가 없는 엔터티 형식 정의

키가 없는 엔터티 형식은 데이터 주석 또는 Fluent API를 사용 하 여 정의할 수 있습니다.

[Keyless]
public class BlogPostsCount
{
    public string BlogName { get; set; }
    public int PostCount { get; set; }
}

키가 없는 엔터티 형식 특징

키가 없는 엔터티 형식은 상속 매핑 및 탐색 속성과 같은 일반적인 엔터티 형식과 동일한 매핑 기능을 대부분 지원 합니다. 관계형 저장소에서 흐름 API 메서드 또는 데이터 주석을 통해 대상 데이터베이스 개체 및 열을 구성할 수 있습니다.

그러나 다음과 같은 점에서 일반 엔터티 형식과는 다릅니다.

  • 키를 정의할 수 없습니다.
  • DbContext 의 변경 내용에 대해서는 추적 되지 않으므로 데이터베이스에 삽입, 업데이트 또는 삭제 되지 않습니다.
  • 규칙에 따라 검색 되지 않습니다.
  • 는 다음과 같이 탐색 매핑 기능의 하위 집합만 지원 합니다.
    • 관계의 주 끝으로 작동 하지 않을 수 있습니다.
    • 소유 된 엔터티를 탐색 하지 못할 수 있습니다.
    • 일반 엔터티를 가리키는 참조 탐색 속성만 포함할 수 있습니다.
    • 엔터티는 키가 없는 엔터티 형식에 대 한 탐색 속성을 포함할 수 없습니다.
  • [Keyless]데이터 주석이 나 메서드 호출로 구성 해야 .HasNoKey() 합니다.
  • 정의 쿼리에매핑될 수 있습니다. 정의 쿼리는 키가 없는 엔터티 형식에 대 한 데이터 소스 역할을 하는 모델에 선언 된 쿼리입니다.

사용 시나리오

키가 없는 엔터티 형식에 대 한 몇 가지 주요 사용 시나리오는 다음과 같습니다.

  • 원시 SQL 쿼리에대 한 반환 형식으로 제공 됩니다.
  • 기본 키가 포함 되지 않은 데이터베이스 뷰에 매핑됩니다.
  • 기본 키가 정의 되어 있지 않은 테이블에 매핑합니다.
  • 모델에 정의 된 쿼리에 매핑합니다.

데이터베이스 개체에 매핑

흐름 API를 사용 하 여 키가 없는 엔터티 형식을 데이터베이스 개체에 매핑할 ToTableToView 있습니다. EF Core 관점에서이 메서드에 지정 된 데이터베이스 개체는 뷰가읽기 전용 쿼리 원본으로 처리 되 고 update, insert 또는 delete 작업의 대상일 수 없음을 의미 합니다. 그러나 데이터베이스 개체가 실제로 데이터베이스 뷰가 되어야 한다는 의미는 아닙니다. 또는 읽기 전용으로 처리 되는 데이터베이스 테이블 일 수도 있습니다. 반대로 EF Core, 일반 엔터티 형식의 경우 메서드에 지정 된 데이터베이스 개체를 테이블로 처리할 수 있다고 가정 합니다 ToTable . 즉, ToTable쿼리 원본으로 사용할 수 있지만 업데이트, 삭제 및 삽입 작업의 대상으로 사용할 수 있습니다. 실제로에서 데이터베이스 뷰의 이름을 지정할 수 있으며, ToTable 데이터베이스에서 뷰를 업데이트할 수 있도록 구성 하는 한 모든 것이 제대로 작동 해야 합니다.

참고

EF Core 5.0 까지는 ToView 개체가 데이터베이스에 이미 존재 하 고 마이그레이션에 의해 생성 되지 않았다고 가정 합니다. EF Core 5.0 이상에서는 마이그레이션 modelBuilder.Entity<ViewType>().ToTable("ViewNameInDatabase", t => t.ExcludeFromMigrations()) 에서 개체를 제외 하는 데를 사용 합니다. 자세한 내용은 modelBuilder.Entity<ViewType>().ToTable("ViewNameInDatabase", t => t.ExcludeFromMigrations()).

예제

다음 예제에서는 키가 없는 엔터티 형식을 사용 하 여 데이터베이스 뷰를 쿼리 하는 방법을 보여 줍니다.

GitHub에서 이 문서의 샘플을 볼 수 있습니다.

먼저 간단한 블로그 및 사후 모델을 정의 합니다.

public class Blog
{
    public int BlogId { get; set; }
    public string Name { get; set; }
    public string Url { get; set; }
    public ICollection<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public int BlogId { get; set; }
}

다음으로, 각 블로그의 연결 된 게시물 수를 쿼리 하는 데 사용할 수 있는 간단한 데이터베이스 뷰를 정의 합니다.

db.Database.ExecuteSqlRaw(
    @"CREATE VIEW View_BlogPostCounts AS
        SELECT b.Name, Count(p.PostId) as PostCount
        FROM Blogs b
        JOIN Posts p on p.BlogId = b.BlogId
        GROUP BY b.Name");

다음에는 데이터베이스 뷰의 결과를 저장 하는 클래스를 정의 합니다.

public class BlogPostsCount
{
    public string BlogName { get; set; }
    public int PostCount { get; set; }
}

그런 다음 API를 사용 하 여 Onmodelcreating 에서 엔터티 형식을 구성 합니다 . 흐름 구성 API를 사용 하 여 키가 없는 엔터티 형식에 대 한 매핑을 구성 합니다.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Entity<BlogPostsCount>(
            eb =>
            {
                eb.HasNoKey();
                eb.ToView("View_BlogPostCounts");
                eb.Property(v => v.BlogName).HasColumnName("Name");
            });
}

다음으로를 구성 하 여를 포함 하도록를 구성 합니다 DbContextDbSet<T> .

public DbSet<BlogPostsCount> BlogPostCounts { get; set; }

마지막으로 다음과 같은 표준 방식으로 데이터베이스 뷰를 쿼리할 수 있습니다.

var postCounts = db.BlogPostCounts.ToList();

foreach (var postCount in postCounts)
{
    Console.WriteLine($"{postCount.BlogName} has {postCount.PostCount} posts.");
    Console.WriteLine();
}

참고로,이 형식에 대 한 쿼리의 루트 역할을 하는 데 사용할 컨텍스트 수준 쿼리 속성 (DbSet)도 정의 했습니다.

메모리 내 공급자를 사용 하 여 뷰에 매핑된 키가 없는 엔터티 형식을 테스트 하려면를 통해 쿼리에 매핑합니다 ToInMemoryQuery . 자세한 내용은이 기법을 사용 하 여 실행 가능한 샘플 을 참조 하세요.