EF Core 매핑 EntityTypeConfiguration
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 });
}
}
이것이 제가 현재 작업중인 프로젝트에서하고있는 일입니다.
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가 솔루션 탐색기에서 파일을 접습니다. 엔티티 클래스 파일 아래에 포함되도록합니다.
이 솔루션으로 끝났습니다.
public interface IEntityMappingConfiguration
{
void Map(ModelBuilder b);
}
public interface IEntityMappingConfiguration<T> : IEntityMappingConfiguration where T : class
{
void Map(EntityTypeBuilder<T> builder);
}
public abstract class EntityMappingConfiguration<T> : IEntityMappingConfiguration<T> where T : class
{
public abstract void Map(EntityTypeBuilder<T> b);
public void Map(ModelBuilder b)
{
Map(b.Entity<T>());
}
}
public static class ModelBuilderExtenions
{
private static IEnumerable<Type> GetMappingTypes(this Assembly assembly, Type mappingInterface)
{
return assembly.GetTypes().Where(x => !x.IsAbstract && x.GetInterfaces().Any(y => y.GetTypeInfo().IsGenericType && y.GetGenericTypeDefinition() == mappingInterface));
}
public static void AddEntityConfigurationsFromAssembly(this ModelBuilder modelBuilder, Assembly assembly)
{
var mappingTypes = assembly.GetMappingTypes(typeof (IEntityMappingConfiguration<>));
foreach (var config in mappingTypes.Select(Activator.CreateInstance).Cast<IEntityMappingConfiguration>())
{
config.Map(modelBuilder);
}
}
}
샘플 사용 :
public abstract class PersonConfiguration : EntityMappingConfiguration<Person>
{
public override void Map(EntityTypeBuilder<Person> b)
{
b.ToTable("Person", "HumanResources")
.HasKey(p => p.PersonID);
b.Property(p => p.FirstName).HasMaxLength(50).IsRequired();
b.Property(p => p.MiddleName).HasMaxLength(50);
b.Property(p => p.LastName).HasMaxLength(50).IsRequired();
}
}
과
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.AddEntityConfigurationsFromAssembly(GetType().Assembly);
}
IEntityTypeConfiguration을 구현하십시오.
public abstract class EntityTypeConfiguration<TEntity> : IEntityTypeConfiguration<TEntity> where TEntity : class
{
public abstract void Configure(EntityTypeBuilder<TEntity> builder);
}
그런 다음 엔티티 컨텍스트에 추가하십시오.
public class ProductContext : DbContext, IDbContext
{
public ProductContext(DbContextOptions<ProductContext> options)
: base((DbContextOptions)options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfiguration(new ProductMap());
}
public DbSet<Entities.Product> Products { get; set; }
}
내가 맞아?
public class SmartModelBuilder<T> where T : class {
private ModelBuilder _builder { get; set; }
private Action<EntityTypeBuilder<T>> _entityAction { get; set; }
public SmartModelBuilder(ModelBuilder builder, Action<EntityTypeBuilder<T>> entityAction)
{
this._builder = builder;
this._entityAction = entityAction;
this._builder.Entity<T>(_entityAction);
}
}
구성을 전달할 수 있습니다.
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);
new SmartModelBuilder<Blog>(builder, entity => entity.Property(b => b.Url).Required());
}
Microsoft가 ForSqlServerToTable을 구현하는 방식과 유사한 접근 방식을 따랐습니다.
확장 방법 사용 중 ...
부분 여러 파일에서 같은 클래스 이름을 사용하려는 경우 플래그가 필요합니다
public class ConsignorUser
{
public int ConsignorId { get; set; }
public string UserId { get; set; }
public virtual Consignor Consignor { get; set; }
public virtual User User { get; set; }
}
public static partial class Entity_FluentMappings
{
public static EntityTypeBuilder<ConsignorUser> AddFluentMapping<TEntity> (
this EntityTypeBuilder<ConsignorUser> entityTypeBuilder)
where TEntity : ConsignorUser
{
entityTypeBuilder.HasKey(x => new { x.ConsignorId, x.UserId });
return entityTypeBuilder;
}
}
그런 다음 DataContext OnModelCreating 에서 각 확장에 대해 호출하십시오.
public class DataContext : IdentityDbContext<User>
{
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Customize the ASP.NET Identity model and override the defaults if needed.
// For example, you can rename the ASP.NET Identity table names and more.
// Add your customizations after calling base.OnModelCreating(builder);
builder.Entity<ConsignorUser>().AddFluentMapping<ConsignorUser>();
builder.Entity<DealerUser>().AddFluentMapping<DealerUser>();
}
이렇게 하면 다른 빌더 메서드에서 사용 하는 것과 동일한 패턴을 따릅니다.
당신은 무엇을합니까?
다음은 EF7 Github 리포지토리의 개선 사항에 대한 문제입니다. https://github.com/aspnet/EntityFramework/issues/2805
여기서 문제를 직접 추적 할 수 있지만 우선 순위가 지정되지 않은 백 로그에만 남아 있습니다.
외부에서 엔터티를 구성 할 수있는 프로젝트가 있습니다. DbContext.OnModelCreating
각 엔터티를 상속하는 별도의 클래스로 구성합니다.StaticDotNet.EntityFrameworkCore.ModelConfiguration.EntityTypeConfiguration
먼저 구성하려는 클래스가있는 StaticDotNet.EntityFrameworkCore.ModelConfiguration.EntityTypeConfiguration<TEntity>
위치 에서 상속하는 클래스를 만들어야 TEntity
합니다.
using StaticDotNet.EntityFrameworkCore.ModelConfiguration;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
public class ExampleEntityConfiguration
: EntityTypeConfiguration<ExampleEntity>
{
public override void Configure( EntityTypeBuilder<ExampleEntity> builder )
{
//Add configuration just like you do in DbContext.OnModelCreating
}
}
그런 다음 Startup 클래스에서 DbContext를 구성 할 때 모든 구성 클래스를 찾을 위치를 Entity Framework에 지정하기 만하면됩니다.
using StaticDotNet.EntityFrameworkCore.ModelConfiguration;
public void ConfigureServices(IServiceCollection services)
{
Assembly[] assemblies = new Assembly[]
{
// Add your assembiles here.
};
services.AddDbContext<ExampleDbContext>( x => x
.AddEntityTypeConfigurations( assemblies )
);
}
공급자를 사용하여 유형 구성을 추가하는 옵션도 있습니다. 저장소에는 사용 방법에 대한 완전한 문서가 있습니다.
https://github.com/john-t-white/StaticDotNet.EntityFrameworkCore.ModelConfiguration
ef core에서는 EntityTypeConfiguration 대신 IEntityTypeConfiguration 요소를 추가해야합니다.이 경우 DbContext modelBuilder에 대한 전체 액세스 권한이 있고 유창한 API를 사용할 수 있지만 ef core에서는이 API가 이전 버전과 약간 다릅니다. ef 핵심 모델 구성에 대한 자세한 내용은
https://www.learnentityframeworkcore.com/configuration/fluent-api
Entity Framework Core 2.0에서 :
Cocowalla의 답변을 가져와 v2.0에 적용했습니다.
public static class ModelBuilderExtenions
{
private static IEnumerable<Type> GetMappingTypes(this Assembly assembly, Type mappingInterface)
{
return assembly.GetTypes().Where(x => !x.IsAbstract && x.GetInterfaces().Any(y => y.GetTypeInfo().IsGenericType && y.GetGenericTypeDefinition() == mappingInterface));
}
public static void AddEntityConfigurationsFromAssembly(this ModelBuilder modelBuilder, Assembly assembly)
{
// Types that do entity mapping
var mappingTypes = assembly.GetMappingTypes(typeof(IEntityTypeConfiguration<>));
// 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(modelBuilder, null);
// Create the mapping type and do the mapping
var mapper = Activator.CreateInstance(mappingType);
mapper.GetType().GetMethod("Configure").Invoke(mapper, new[] { entityBuilder });
}
}
}
그리고 다음과 같이 DbContext에서 사용됩니다.
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.AddEntityConfigurationsFromAssembly(GetType().Assembly);
}
엔터티에 대한 엔터티 유형 구성을 만드는 방법은 다음과 같습니다.
public class UserUserRoleEntityTypeConfiguration : IEntityTypeConfiguration<UserUserRole>
{
public void Configure(EntityTypeBuilder<UserUserRole> builder)
{
builder.ToTable("UserUserRole");
// compound PK
builder.HasKey(p => new { p.UserId, p.UserRoleId });
}
}
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);
}
}
참고 URL : https://stackoverflow.com/questions/26957519/ef-core-mapping-entitytypeconfiguration
'Programing' 카테고리의 다른 글
Mongo 컬렉션을 JSON 형식으로 덤프 (0) | 2020.08.13 |
---|---|
mongodb는 CAP 정리에서 어디에 서 있습니까? (0) | 2020.08.13 |
UITextView에서 복사, 잘라 내기, 선택, 모두 선택을 비활성화하는 방법 (0) | 2020.08.12 |
Android의 가비지 수집기 (0) | 2020.08.12 |
plot.new () 오류 : R에서 그림 여백이 너무 큽니다. (0) | 2020.08.12 |