EF Core 매핑 EntityTypeConfiguration => a.Id);

EF6에서는 일반적으로이 방법을 사용하여 엔티티를 구성 할 수 있습니다.

public class AccountMap : EntityTypeConfiguration<Account>
{
    public AccountMap()
    {
        ToTable("Account");
        HasKey(a => a.Id);

        Property(a => a.Username).HasMaxLength(50);
        Property(a => a.Email).HasMaxLength(255);
        Property(a => a.Name).HasMaxLength(255);
    }
}

클래스 I Inherit EntityTypeConfiguration이 클래스를 찾을 수 없기 때문에 EF Core에서 할 수있는 방법.

GitHub에서 EF Core 원시 소스 코드를 다운로드했는데 찾을 수 없습니다. 누군가 이것을 도울 수 있습니까?



답변

EF Core 2.0부터 IEntityTypeConfiguration<TEntity>. 다음과 같이 사용할 수 있습니다.

class CustomerConfiguration : IEntityTypeConfiguration<Customer>
{
  public void Configure(EntityTypeBuilder<Customer> builder)
  {
     builder.HasKey(c => c.AlternateKey);
     builder.Property(c => c.Name).HasMaxLength(200);
   }
}

...
// OnModelCreating
builder.ApplyConfiguration(new CustomerConfiguration());

이 기능과 2.0에 도입 된 기타 새로운 기능에 대한 자세한 내용은 여기 에서 확인할 수 있습니다 .


답변

몇 가지 간단한 추가 유형을 통해이를 달성 할 수 있습니다.

internal static class ModelBuilderExtensions
{
   public static void AddConfiguration<TEntity>(
     this ModelBuilder modelBuilder,
     DbEntityConfiguration<TEntity> entityConfiguration) where TEntity : class
   {
       modelBuilder.Entity<TEntity>(entityConfiguration.Configure);
   }
}

internal abstract class DbEntityConfiguration<TEntity> where TEntity : class
{
    public abstract void Configure(EntityTypeBuilder<TEntity> entity);
}

용법:

internal class UserConfiguration : DbEntityConfiguration<UserDto>
{
    public override void Configure(EntityTypeBuilder<UserDto> entity)
    {
        entity.ToTable("User");
        entity.HasKey(c => c.Id);
        entity.Property(c => c.Username).HasMaxLength(255).IsRequired();
        // etc.
    }
}

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    modelBuilder.AddConfiguration(new UserConfiguration());
}

답변

EF7에서는 구현중인 DbContext 클래스에서 OnModelCreating을 재정의합니다.

protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Account>()
            .ForRelational(builder => builder.Table("Account"))
            .Property(value => value.Username).MaxLength(50)
            .Property(value => value.Email).MaxLength(255)
            .Property(value => value.Name).MaxLength(255);
    }

답변

현재 최신 베타 8을 사용하고 있습니다. 다음을 시도해보세요.

public class AccountMap
{
    public AccountMap(EntityTypeBuilder<Account> entityBuilder)
    {
        entityBuilder.HasKey(x => x.AccountId);

        entityBuilder.Property(x => x.AccountId).IsRequired();
        entityBuilder.Property(x => x.Username).IsRequired().HasMaxLength(50);
    }
}

그런 다음 DbContext에서 :

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        new AccountMap(modelBuilder.Entity<Account>());
    }

답변

리플렉션을 사용하여 각 엔터티에 대한 별도의 매핑 클래스를 사용하여 EF6에서 작동하는 방식과 매우 유사한 작업을 수행 할 수 있습니다. 이것은 RC1 final에서 작동합니다.

먼저 매핑 유형에 대한 인터페이스를 만듭니다.

public interface IEntityTypeConfiguration<TEntityType> where TEntityType : class
{
    void Map(EntityTypeBuilder<TEntityType> builder);
}

그런 다음 각 엔티티 (예 : 클래스)에 대한 매핑 클래스를 만듭니다 Person.

public class PersonMap : IEntityTypeConfiguration<Person>
{
    public void Map(EntityTypeBuilder<Person> builder)
    {
        builder.HasKey(x => x.Id);
        builder.Property(x => x.Name).IsRequired().HasMaxLength(100);
    }
}

지금의 반사 마법 OnModelCreating귀하의 DbContext구현 :

protected override void OnModelCreating(ModelBuilder builder)
{
    base.OnModelCreating(builder);

    // Interface that all of our Entity maps implement
    var mappingInterface = typeof(IEntityTypeConfiguration<>);

    // Types that do entity mapping
    var mappingTypes = typeof(DataContext).GetTypeInfo().Assembly.GetTypes()
        .Where(x => x.GetInterfaces().Any(y => y.GetTypeInfo().IsGenericType && y.GetGenericTypeDefinition() == mappingInterface));

    // Get the generic Entity method of the ModelBuilder type
    var entityMethod = typeof(ModelBuilder).GetMethods()
        .Single(x => x.Name == "Entity" &&
                x.IsGenericMethod &&
                x.ReturnType.Name == "EntityTypeBuilder`1");

    foreach (var mappingType in mappingTypes)
    {
        // Get the type of entity to be mapped
        var genericTypeArg = mappingType.GetInterfaces().Single().GenericTypeArguments.Single();

        // Get the method builder.Entity<TEntity>
        var genericEntityMethod = entityMethod.MakeGenericMethod(genericTypeArg);

        // Invoke builder.Entity<TEntity> to get a builder for the entity to be mapped
        var entityBuilder = genericEntityMethod.Invoke(builder, null);

        // Create the mapping type and do the mapping
        var mapper = Activator.CreateInstance(mappingType);
        mapper.GetType().GetMethod("Map").Invoke(mapper, new[] { entityBuilder });
    }
}

답변

EF Core 2.2부터는 DbContext 클래스에서 상속 된 클래스의 OnModelCreating 메서드에서 한 줄에 모든 구성 (IEntityTypeConfiguration 인터페이스를 구현 한 클래스)을 추가 할 수 있습니다.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    //this will apply configs from separate classes which implemented IEntityTypeConfiguration<T>
    modelBuilder.ApplyConfigurationsFromAssembly(Assembly.GetExecutingAssembly());
}

그리고 이전 답변에서 언급했듯이 EF Core 2.0부터 IEntityTypeConfiguration 인터페이스를 구현하고 Configure 메서드에서 FluentAPI를 사용하여 매핑 구성을 설정할 수 있습니다.

public class QuestionAnswerConfig : IEntityTypeConfiguration<QuestionAnswer>
{
    public void Configure(EntityTypeBuilder<QuestionAnswer> builder)
    {
      builder
        .HasKey(bc => new { bc.QuestionId, bc.AnswerId });
      builder
        .HasOne(bc => bc.Question)
        .WithMany(b => b.QuestionAnswers)
        .HasForeignKey(bc => bc.QuestionId);
      builder
        .HasOne(bc => bc.Answer)
        .WithMany(c => c.QuestionAnswers)
        .HasForeignKey(bc => bc.AnswerId);
    }
}

답변

이것이 제가 현재 작업중인 프로젝트에서하고있는 일입니다.

public interface IEntityMappingConfiguration<T> where T : class
{
    void Map(EntityTypeBuilder<T> builder);
}

public static class EntityMappingExtensions
{
     public static ModelBuilder RegisterEntityMapping<TEntity, TMapping>(this ModelBuilder builder)
        where TMapping : IEntityMappingConfiguration<TEntity>
        where TEntity : class
    {
        var mapper = (IEntityMappingConfiguration<TEntity>)Activator.CreateInstance(typeof (TMapping));
        mapper.Map(builder.Entity<TEntity>());
        return builder;
    }
}

용법:

컨텍스트의 OnModelCreating 메서드에서 :

    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);

        builder
            .RegisterEntityMapping<Card, CardMapping>()
            .RegisterEntityMapping<User, UserMapping>();
    }

매핑 클래스의 예 :

public class UserMapping : IEntityMappingConfiguration<User>
{
    public void Map(EntityTypeBuilder<User> builder)
    {
        builder.ToTable("User");
        builder.HasKey(m => m.Id);
        builder.Property(m => m.Id).HasColumnName("UserId");
        builder.Property(m => m.FirstName).IsRequired().HasMaxLength(64);
        builder.Property(m => m.LastName).IsRequired().HasMaxLength(64);
        builder.Property(m => m.DateOfBirth);
        builder.Property(m => m.MobileNumber).IsRequired(false);
    }
}

Visual Studio 2015의 접기 동작을 활용하기 위해 제가 좋아하는 또 하나는 ‘User’라는 엔티티에 대한 것입니다. 매핑 파일의 이름을 ‘User.Mapping.cs’로 지정하면 Visual Studio가 솔루션 탐색기에서 파일을 접습니다. 엔티티 클래스 파일 아래에 포함되도록합니다.