엔터티 형식
컨텍스트에 형식의 DbSet을 포함하면 EF Core의 모델에 포함됩니다. 일반적으로 이러한 형식을 엔터티라고 합니다. EF Core는 데이터베이스 간에 엔터티 인스턴스를 읽고 쓸 수 있으며, 관계형 데이터베이스를 사용하는 경우 EF Core는 마이그레이션을 통해 엔터티에 대한 테이블을 만들 수 있습니다.
모델에 형식 포함
규칙에 따라 컨텍스트의 DbSet 속성에 노출되는 형식은 모델에 엔터티로 포함됩니다. OnModelCreating
메서드에 지정된 엔터티 형식도 포함되며, 검색된 다른 엔터티 형식의 탐색 속성을 재귀적으로 탐색하여 찾은 모든 형식도 포함됩니다.
아래 코드 샘플에서는 모든 형식이 포함됩니다.
Blog
는 컨텍스트의 DbSet 속성에 노출되기 때문에 포함됩니다.Post
는Blog.Posts
탐색 속성을 통해 검색되기 때문에 포함됩니다.AuditEntry
는OnModelCreating
에 지정되어 있기 때문입니다.
internal class MyContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<AuditEntry>();
}
}
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public Blog Blog { get; set; }
}
public class AuditEntry
{
public int AuditEntryId { get; set; }
public string Username { get; set; }
public string Action { get; set; }
}
모델에서 형식 제외
모델에 형식을 포함하지 않으려면 제외할 수 있습니다.
[NotMapped]
public class BlogMetadata
{
public DateTime LoadedFromDatabase { get; set; }
}
마이그레이션에서 제외
여러 DbContext
에서 동일한 엔터티 형식을 매핑하는 것이 유용한 경우가 있습니다. 바인딩된 컨텍스트를 사용하는 경우에 특히 유용한데, 일반적으로 각 바인딩된 컨텍스에 다른 DbContext
형식을 사용하기 때문입니다.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<IdentityUser>()
.ToTable("AspNetUsers", t => t.ExcludeFromMigrations());
}
이 구성 마이그레이션을 사용하면 AspNetUsers
테이블을 만들지 않지만 IdentityUser
가 모델에 계속 포함되며 정상적으로 사용할 수 있습니다.
마이그레이션을 사용하여 테이블 관리를 다시 시작해야 하는 경우 AspNetUsers
가 제외되지 않은 새 마이그레이션을 만들어야 합니다. 이제 다음 마이그레이션에는 테이블에 대한 변경 내용이 포함됩니다.
테이블 이름
규칙에 따라 각 엔터티 유형은 엔터티를 노출하는 DbSet 속성과 이름이 같은 데이터베이스 테이블에 매핑되도록 설정됩니다. 지정된 엔터티에 대해 DbSet 값이 없으면 클래스 이름이 사용됩니다.
테이블 이름을 수동으로 구성할 수 있습니다.
[Table("blogs")]
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
}
테이블 스키마
관계형 데이터베이스를 사용하는 경우 테이블은 데이터베이스의 기본 스키마에서 만든 규칙에 따라 생성됩니다. 예를 들어 Microsoft SQL Server는 dbo
스키마를 사용합니다(SQLite는 스키마를 지원하지 않음).
다음과 같이 특정 스키마에서 만들 테이블을 구성할 수 있습니다.
[Table("blogs", Schema = "blogging")]
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
}
각 테이블에 대한 스키마를 지정하는 대신 흐름 API를 사용하여 모델 수준에서 기본 스키마를 정의할 수도 있습니다.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("blogging");
}
기본 스키마를 설정하면 시퀀스 같은 다른 데이터베이스 개체에도 영향을 줍니다.
매핑 보기
Fluent API를 사용하여 엔터티 형식을 데이터베이스 뷰에 매핑할 수 있습니다.
참고 항목
EF는 참조된 뷰가 데이터베이스에 이미 있다고 가정하고 마이그레이션에서 자동으로 만들지 않습니다.
modelBuilder.Entity<Blog>()
.ToView("blogsView", schema: "blogging");
뷰에 매핑하면 기본 테이블 매핑이 제거되지만 엔터티 형식을 테이블에 명시적으로 매핑할 수도 있습니다. 이 경우 쿼리 매핑이 쿼리에 사용되고 테이블 매핑이 업데이트에 사용됩니다.
팁
메모리 내 공급자를 사용하여 뷰에 매핑된 키 없는 엔터티 형식을 테스트하려면 ToInMemoryQuery를 통해 쿼리에 매핑합니다. 자세한 내용은 메모리 내 공급자 문서를 참조하세요.
테이블 반환 함수 매핑
데이터베이스의 테이블 대신 TVF(테이블 반환 함수)에 엔터티 형식을 매핑할 수 있습니다. 이를 설명하기 위해 여러 게시물이 있는 블로그를 나타내는 다른 엔터티를 정의해 보겠습니다. 이 예제에서 엔터티는 키가 없지만 키는 필요하지 않습니다.
public class BlogWithMultiplePosts
{
public string Url { get; set; }
public int PostCount { get; set; }
}
다음으로 데이터베이스에서 다음 테이블 반환 함수를 만듭니다. 이 함수는 여러 게시물이 있는 블로그와 이러한 각 블로그와 연결된 게시물 수만 반환합니다.
CREATE FUNCTION dbo.BlogsWithMultiplePosts()
RETURNS TABLE
AS
RETURN
(
SELECT b.Url, COUNT(p.BlogId) AS PostCount
FROM Blogs AS b
JOIN Posts AS p ON b.BlogId = p.BlogId
GROUP BY b.BlogId, b.Url
HAVING COUNT(p.BlogId) > 1
)
이제 다음과 같은 방법으로 엔터티 BlogWithMultiplePosts
를 이 함수에 매핑할 수 있습니다.
modelBuilder.Entity<BlogWithMultiplePosts>().HasNoKey().ToFunction("BlogsWithMultiplePosts");
참고 항목
엔터티를 테이블 반환 함수에 매핑하려면 함수가 매개 변수가 없어야 합니다.
일반적으로 엔터티 속성은 TVF에서 반환하는 일치하는 열에 매핑됩니다. TVF에서 반환하는 열의 이름이 엔터티 속성과 다른 경우 일반 테이블에 매핑할 때와 마찬가지로 HasColumnName
메서드를 사용하여 엔터티의 열을 구성할 수 있습니다.
엔터티 형식이 테이블 반환 함수에 매핑되면 쿼리는 다음과 같습니다.
var query = from b in context.Set<BlogWithMultiplePosts>()
where b.PostCount > 3
select new { b.Url, b.PostCount };
다음 SQL을 생성합니다.
SELECT [b].[Url], [b].[PostCount]
FROM [dbo].[BlogsWithMultiplePosts]() AS [b]
WHERE [b].[PostCount] > 3
테이블 주석
데이터베이스 테이블에 설정된 임의의 텍스트 주석을 설정하여 데이터베이스에서 스키마를 문서화할 수 있습니다.
[Comment("Blogs managed on the website")]
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
}
공유 형식 엔터티 형식 및 속성 모음
동일한 CLR 형식을 사용하는 엔터티 형식을 공유 형식 엔터티 형식이라고 합니다. 이러한 엔터티 형식은 CLR 형식 외에도 공유 형식 엔터티 형식을 사용할 때마다 제공해야 하는 고유한 이름으로 구성해야 합니다. 즉, Set
호출을 사용하여 해당 DbSet
속성을 구현해야 합니다.
internal class MyContext : DbContext
{
public DbSet<Dictionary<string, object>> Blogs => Set<Dictionary<string, object>>("Blog");
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.SharedTypeEntity<Dictionary<string, object>>(
"Blog", bb =>
{
bb.Property<int>("BlogId");
bb.Property<string>("Url");
bb.Property<DateTime>("LastUpdated");
});
}
}
.NET