다음을 통해 공유


모델 만들기 및 구성

EF Core는 메타데이터 모델을 사용하여 애플리케이션의 엔터티 형식이 기본 데이터베이스에 매핑되는 방법을 설명합니다. 이 모델은 일반적인 패턴을 찾는 추론이라는 규칙 집합을 사용하여 빌드됩니다. 그런 다음 매핑 특성(데이터 주석이라고도 함) 및/또는 메서드(ModelBuilder라고도 함)대한 호출 OnModelCreating 을 사용하여 모델을 사용자 지정할 수 있으며, 둘 다 규칙에 의해 수행되는 구성을 재정의합니다.

대부분의 구성은 데이터 저장소를 대상으로 하는 모델에 적용할 수 있습니다. 또한 공급자는 특정 데이터 저장소와 관련된 구성을 사용하도록 설정할 수 있으며 지원되지 않거나 적용되지 않는 구성을 무시할 수도 있습니다. 공급자별 구성에 대한 설명서는 데이터베이스 공급자 섹션을 참조하세요 .

팁 (조언)

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

Fluent API를 사용하여 모델 구성

파생 컨텍스트에서 OnModelCreating 메서드를 재정의하고, Fluent API를 사용하여 모델을 구성할 수 있습니다. 가장 강력한 구성 방법이며 엔터티 클래스를 수정하지 않고도 구성을 지정할 수 있습니다. Fluent API 구성은 우선 순위가 가장 높으며 규칙 및 데이터 주석을 재정의합니다. 구성은 메서드가 호출되는 순서대로 적용되며 충돌이 있는 경우 최신 호출이 이전에 지정한 구성을 재정의합니다.

using Microsoft.EntityFrameworkCore;

namespace EFModeling.EntityProperties.FluentAPI.Required;

internal class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }

    #region Required
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Blog>()
            .Property(b => b.Url)
            .IsRequired();
    }
    #endregion
}

public class Blog
{
    public int BlogId { get; set; }
    public string Url { get; set; }
}

팁 (조언)

모델의 여러 개체에 동일한 구성을 적용하려면 대량 구성을 참조하세요.

그룹화 구성

메서드의 OnModelCreating 크기를 줄이기 위해 엔터티 형식에 대한 모든 구성을 구현하는 IEntityTypeConfiguration<TEntity>별도의 클래스로 추출할 수 있습니다.

public class BlogEntityTypeConfiguration : IEntityTypeConfiguration<Blog>
{
    public void Configure(EntityTypeBuilder<Blog> builder)
    {
        builder
            .Property(b => b.Url)
            .IsRequired();
    }
}

그런 다음 Configure에서 OnModelCreating 메서드를 호출하기만 하면 됩니다.

new BlogEntityTypeConfiguration().Configure(modelBuilder.Entity<Blog>());

어셈블리의 모든 구성 적용

지정된 어셈블리 내에서 구현하는 형식의 모든 구성을 적용할 수 있습니다.

modelBuilder.ApplyConfigurationsFromAssembly(typeof(BlogEntityTypeConfiguration).Assembly);

비고

구성이 적용되는 순서는 정의되지 않으므로 이 메서드는 순서가 중요하지 않은 경우에만 사용해야 합니다.

엔터티 유형에 EntityTypeConfigurationAttribute 사용하기

명시적으로 Configure를 호출하는 대신 EntityTypeConfigurationAttribute을 엔터티 형식에 배치하여 EF Core가 적절한 구성을 찾고 사용할 수 있도록 할 수 있습니다. 다음은 그 예입니다.

[EntityTypeConfiguration(typeof(BookConfiguration))]
public class Book
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Isbn { get; set; }
}

이 특성은 IEntityTypeConfiguration 엔터티 형식이 모델에 포함될 때마다 EF Core가 지정된 Book 구현을 사용한다는 것을 의미합니다. 엔터티 형식은 일반 메커니즘 중 하나를 사용하여 모델에 포함됩니다. 예를 들어 엔터티 형식에 DbSet<TEntity> 대한 속성을 만듭니다.

public class BooksContext : DbContext
{
    public DbSet<Book> Books { get; set; }

    //...

또는 다음에서 등록합니다.OnModelCreating

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Book>();
}

비고

EntityTypeConfigurationAttribute 형식은 어셈블리에서 자동으로 검색되지 않습니다. 해당 엔터티 형식에서 특성을 검색하려면 먼저 모델에 엔터티 형식을 추가해야 합니다.

데이터 주석을 사용하여 모델 구성

특정 특성( 데이터 주석이라고도 함)을 클래스 및 속성에 적용할 수도 있습니다. 데이터 주석은 관례를 무시하지만, Fluent API 구성에 의해 덮어쓰기가 됩니다.

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;

namespace EFModeling.EntityProperties.DataAnnotations.Annotations;

internal class MyContext : DbContext
{
    public DbSet<Blog> Blogs { get; set; }
}

[Table("Blogs")]
public class Blog
{
    public int BlogId { get; set; }

    [Required]
    public string Url { get; set; }
}

내장된 관습

EF Core에는 기본적으로 사용하도록 설정되는 많은 모델 빌드 규칙이 포함되어 있습니다. 인터페이스를 구현 IConvention 하는 클래스 목록에서 모두 찾을 수 있습니다. 그러나 이 목록에는 타사 데이터베이스 공급자 및 플러그 인에서 도입한 규칙이 포함되지 않습니다.

애플리케이션은 이러한 규칙을 제거하거나 대체할 수 있으며, EF에서 인식할 수 없는 패턴에 대한 구성을 적용하는 새 사용자 지정 규칙을 기본적으로 추가할 수 있습니다.

팁 (조언)

아래에 표시된 코드는 ModelBuildingConventionsSample.cs 제공됩니다.

기존 규칙 제거

경우에 따라 기본 제공 규칙 중 하나가 애플리케이션에 적합하지 않을 수 있으며, 이 경우 제거할 수 있습니다.

팁 (조언)

모델이 구성에 매핑 특성(즉, 데이터 주석)을 사용하지 않는 경우 이름이 끝나는 AttributeConvention 모든 규칙을 안전하게 제거하여 모델 빌드 속도를 높일 수 있습니다.

예: 외래 키 열에 대한 인덱스를 만들지 마세요.

일반적으로 FK(외래 키) 열에 대한 인덱스를 만드는 것이 합리적이므로 다음과 ForeignKeyIndexConvention같은 기본 제공 규칙이 있습니다. 관계가 Post와 있는 엔터티 형식에 대한 Blog 모델 Author를 검토하면, 두 개의 인덱스가 생성되는데, 하나는 BlogId FK에 대한 것이고, 다른 하나는 AuthorId FK에 대한 것입니다.

  EntityType: Post
    Properties:
      Id (int) Required PK AfterSave:Throw ValueGenerated.OnAdd
      AuthorId (no field, int?) Shadow FK Index
      BlogId (no field, int) Shadow Required FK Index
    Navigations:
      Author (Author) ToPrincipal Author Inverse: Posts
      Blog (Blog) ToPrincipal Blog Inverse: Posts
    Keys:
      Id PK
    Foreign keys:
      Post {'AuthorId'} -> Author {'Id'} ToDependent: Posts ToPrincipal: Author ClientSetNull
      Post {'BlogId'} -> Blog {'Id'} ToDependent: Posts ToPrincipal: Blog Cascade
    Indexes:
      AuthorId
      BlogId

그러나 인덱스에는 오버헤드가 있으며 모든 FK 열에 대해 인덱스를 만드는 것이 항상 적절하지는 않을 수 있습니다. 모델을 빌드할 때 이를 달성하기 위해 ForeignKeyIndexConvention을 제거할 수 있습니다.

protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
{
    configurationBuilder.Conventions.Remove(typeof(ForeignKeyIndexConvention));
}

현재 모델의 디버그 뷰를 Post 살펴보면 FK의 인덱스가 만들어지지 않은 것을 볼 수 있습니다.

  EntityType: Post
    Properties:
      Id (int) Required PK AfterSave:Throw ValueGenerated.OnAdd
      AuthorId (no field, int?) Shadow FK
      BlogId (no field, int) Shadow Required FK
    Navigations:
      Author (Author) ToPrincipal Author Inverse: Posts
      Blog (Blog) ToPrincipal Blog Inverse: Posts
    Keys:
      Id PK
    Foreign keys:
      Post {'AuthorId'} -> Author {'Id'} ToDependent: Posts ToPrincipal: Author ClientSetNull
      Post {'BlogId'} -> Blog {'Id'} ToDependent: Posts ToPrincipal: Blog Cascade

원하는 경우 IndexAttribute 또는 OnModelCreating에서 구성을 사용하여 외래 키 열에 대한 인덱스를 명시적으로 만들 수 있습니다.

디버그 뷰

모델 작성기 디버그 뷰는 IDE의 디버거에서 액세스할 수 있습니다. 예를 들어 Visual Studio를 사용하면 다음과 같습니다.

Visual Studio 디버거에서 모델 작성기 디버그 보기에 액세스

코드에서 직접 액세스할 수도 있습니다. 예를 들어 디버그 보기를 콘솔로 보냅니다.

Console.WriteLine(context.Model.ToDebugString());

디버그 보기에는 짧은 폼과 긴 폼이 있습니다. 긴 양식에는 관계형 또는 공급자별 메타데이터를 확인해야 하는 경우에 유용할 수 있는 모든 주석도 포함됩니다. 긴 보기는 코드에서도 액세스할 수 있습니다.

Console.WriteLine(context.Model.ToDebugString(MetadataDebugStringOptions.LongDefault));