키 없는 엔터티 형식Keyless Entity Types

참고

이 기능은 쿼리 유형 이름 아래 EF Core 2.1에 추가 되었습니다.This feature was added in EF Core 2.1 under the name of query types. EF Core 3.0에서 개념은 키가 없는 엔터티 형식으로 이름이 변경 되었습니다.In EF Core 3.0 the concept was renamed to keyless entity types. [Keyless] 데이터 주석은 efcore 5.0에서 사용할 수 있습니다.The [Keyless] Data Annotation became available in EFCore 5.0.

일반 엔터티 형식 외에도 EF Core 모델에는 키 값이 포함 되지 않은 데이터에 대 한 데이터베이스 쿼리를 수행 하는 데 사용할 수 있는 _키가 없는 엔터티 형식이_포함 될 수 있습니다.In addition to regular entity types, an EF Core model can contain keyless entity types, which can be used to carry out database queries against data that doesn't contain key values.

키가 없는 엔터티 형식 정의Defining Keyless entity types

키가 없는 엔터티 형식은 데이터 주석 또는 흐름 API를 사용 하 여 정의할 수 있습니다.Keyless entity types can be defined using either the Data Annotation or the Fluent API:

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

키가 없는 엔터티 형식 특징Keyless entity types characteristics

키가 없는 엔터티 형식은 상속 매핑 및 탐색 속성과 같은 일반적인 엔터티 형식과 동일한 매핑 기능을 대부분 지원 합니다.Keyless entity types support many of the same mapping capabilities as regular entity types, like inheritance mapping and navigation properties. 관계형 저장소에서 흐름 API 메서드 또는 데이터 주석을 통해 대상 데이터베이스 개체 및 열을 구성할 수 있습니다.On relational stores, they can configure the target database objects and columns via fluent API methods or data annotations.

그러나 다음과 같은 점에서 일반 엔터티 형식과는 다릅니다.However, they are different from regular entity types in that they:

  • 키를 정의할 수 없습니다.Cannot have a key defined.
  • DbContext 의 변경 내용에 대해서는 추적 되지 않으므로 데이터베이스에 삽입, 업데이트 또는 삭제 되지 않습니다.Are never tracked for changes in the DbContext and therefore are never inserted, updated or deleted on the database.
  • 규칙에 따라 검색 되지 않습니다.Are never discovered by convention.
  • 는 다음과 같이 탐색 매핑 기능의 하위 집합만 지원 합니다.Only support a subset of navigation mapping capabilities, specifically:
    • 관계의 주 끝으로 작동 하지 않을 수 있습니다.They may never act as the principal end of a relationship.
    • 소유 된 엔터티를 탐색 하지 못할 수 있습니다.They may not have navigations to owned entities
    • 일반 엔터티를 가리키는 참조 탐색 속성만 포함할 수 있습니다.They can only contain reference navigation properties pointing to regular entities.
    • 엔터티는 키가 없는 엔터티 형식에 대 한 탐색 속성을 포함할 수 없습니다.Entities cannot contain navigation properties to keyless entity types.
  • [Keyless] 데이터 주석이 나 .HasNoKey() 메서드 호출로 구성 해야 합니다.Need to be configured with a [Keyless] data annotation or a .HasNoKey() method call.
  • _정의 쿼리에_매핑될 수 있습니다.May be mapped to a defining query. 정의 쿼리는 키가 없는 엔터티 형식에 대 한 데이터 소스 역할을 하는 모델에 선언 된 쿼리입니다.A defining query is a query declared in the model that acts as a data source for a keyless entity type.

사용 시나리오Usage scenarios

키가 없는 엔터티 형식에 대 한 몇 가지 주요 사용 시나리오는 다음과 같습니다.Some of the main usage scenarios for keyless entity types are:

  • 원시 SQL 쿼리의반환 형식으로 제공 됩니다.Serving as the return type for raw SQL queries.
  • 기본 키가 포함 되지 않은 데이터베이스 뷰에 매핑됩니다.Mapping to database views that do not contain a primary key.
  • 기본 키가 정의 되어 있지 않은 테이블에 매핑합니다.Mapping to tables that do not have a primary key defined.
  • 모델에 정의 된 쿼리에 매핑합니다.Mapping to queries defined in the model.

데이터베이스 개체에 매핑Mapping to database objects

흐름 API를 사용 하 여 ToTable 키가 없는 엔터티 형식을 데이터베이스 개체에 매핑할 수 있습니다. ToViewMapping a keyless entity type to a database object is achieved using the ToTable or ToView fluent API. EF Core 관점에서이 메서드에 지정 된 데이터베이스 개체는 _뷰가_읽기 전용 쿼리 원본으로 처리 되 고 update, insert 또는 delete 작업의 대상일 수 없음을 의미 합니다.From the perspective of EF Core, the database object specified in this method is a view, meaning that it is treated as a read-only query source and cannot be the target of update, insert or delete operations. 그러나 데이터베이스 개체가 실제로 데이터베이스 뷰가 되어야 한다는 의미는 아닙니다.However, this does not mean that the database object is actually required to be a database view. 또는 읽기 전용으로 처리 되는 데이터베이스 테이블 일 수도 있습니다.It can alternatively be a database table that will be treated as read-only. 반대로 EF Core, 일반 엔터티 형식의 경우 ToTable 메서드에 지정 된 데이터베이스 개체를 _테이블로_처리할 수 있다고 가정 합니다. 즉, 쿼리 원본으로 사용할 수 있지만 업데이트, 삭제 및 삽입 작업의 대상으로 사용할 수 있습니다.Conversely, for regular entity types, EF Core assumes that a database object specified in the ToTable method can be treated as a table, meaning that it can be used as a query source but also targeted by update, delete and insert operations. 실제로에서 ToTable 데이터베이스 뷰의 이름을 지정할 수 있으며, 데이터베이스에서 뷰를 업데이트할 수 있도록 구성 하는 한 모든 것이 제대로 작동 해야 합니다.In fact, you can specify the name of a database view in ToTable and everything should work fine as long as the view is configured to be updatable on the database.

참고

ToView에서는 개체가 데이터베이스에 이미 존재 하 고 마이그레이션에 의해 생성 되지 않는다고 가정 합니다.ToView assumes that the object already exists in the database and it won't be created by migrations.

예제Example

다음 예제에서는 키가 없는 엔터티 형식을 사용 하 여 데이터베이스 뷰를 쿼리 하는 방법을 보여 줍니다.The following example shows how to use keyless entity types to query a database view.

GitHub에서이 문서의 샘플 을 볼 수 있습니다.You can view this article's sample on GitHub.

먼저 간단한 블로그 및 사후 모델을 정의 합니다.First, we define a simple Blog and Post model:

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

다음으로, 각 블로그의 연결 된 게시물 수를 쿼리 하는 데 사용할 수 있는 간단한 데이터베이스 뷰를 정의 합니다.Next, we define a simple database view that will allow us to query the number of posts associated with each blog:

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

다음에는 데이터베이스 뷰의 결과를 저장 하는 클래스를 정의 합니다.Next, we define a class to hold the result from the database view:

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

그런 다음 HasNoKey API를 사용 하 여 onmodelcreating 에서 엔터티 형식을 구성 합니다.Next, we configure the keyless entity type in OnModelCreating using the HasNoKey API. 흐름 구성 API를 사용 하 여 키가 없는 엔터티 형식에 대 한 매핑을 구성 합니다.We use fluent configuration API to configure the mapping for the keyless entity type:

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

다음으로를 구성 하 DbContext 여를 포함 DbSet<T>하도록를 구성 합니다.Next, we configure the DbContext to include the DbSet<T>:

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

마지막으로 다음과 같은 표준 방식으로 데이터베이스 뷰를 쿼리할 수 있습니다.Finally, we can query the database view in the standard way:

var postCounts = db.BlogPostCounts.ToList();

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

참고로,이 형식에 대 한 쿼리의 루트 역할을 하는 데 사용할 컨텍스트 수준 쿼리 속성 (DbSet)도 정의 했습니다.Note we have also defined a context level query property (DbSet) to act as a root for queries against this type.