EF Core Mapping EntityTypeConfiguration


129

โดยปกติแล้วใน 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);
    }
}

เราจะทำอย่างไรใน EF Core เนื่องจากเมื่อคลาส I Inherit EntityTypeConfiguration ที่ไม่สามารถค้นหาคลาสได้

ฉันดาวน์โหลดซอร์สโค้ดดิบของ EF Core จาก GitHub ไม่พบ ใครสามารถช่วยในเรื่องนี้?


8
ทำไมไม่ยอมรับคำตอบนั้น
— Den

เนื่องจากใน beta5 ตอนนี้เมื่อเราใส่ maxLength (50) ในฐานข้อมูลจะสร้าง nvarchar (สูงสุด)
— Herman

6
สำหรับใครที่สนใจเรื่องนี้ตอนนี้IEntityTypeConfiguration<T>มีvoid Configure()วิธีการเดียวที่คุณสามารถนำไปใช้ได้ ดูรายละเอียดที่นี่: github.com/aspnet/EntityFramework/pull/6989
— Galilyou

คำตอบ:


183

ตั้งแต่ 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 สามารถพบได้ที่นี่


8
นี่คือคำตอบที่ดีที่สุดสำหรับ EF Core 2.0 ขอบคุณ!
— Collin M. Barrett

2
ยอดเยี่ยมมาก ฉันกำลังมองหาวิธีแยกคำจำกัดความ API ที่คล่องแคล่ว ขอบคุณ
— Blaze

ดูคำตอบสำหรับ "ToTable" และ "HasColumnName" เป็นต้น ::: stackoverflow.com/questions/43200184/…
— granadaCoder

หากคุณมีการกำหนดค่าที่กำหนดเองสำหรับผู้ชายเพียงแค่ใส่ builder.ApplyConfigurationsFromAssembly(typeof(ApplicationDbContext).Assembly);มันจะใช้การยืนยันที่กำหนดเองทั้งหมด
— alim91

52

คุณสามารถบรรลุสิ่งนี้ได้ด้วยประเภทเพิ่มเติมง่ายๆ:

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

1
อยู่ที่ไหนForSqlServerToTable()?
— im1dermike


1
วิธีใช้HasColumnTypeกับสิ่งนี้? . สำหรับเช่น entity.Property(c => c.JoinDate).HasColumnType("date");
— Biju Soman

OnModelCreatingได้รับการอัปเดตเพื่อต้องการไฟล์DbModelBuilder. วิธีเพิ่มการกำหนดค่าในตอนนี้คือmodelBuilder.Configurations.Add(new UserConfiguration());
— Izzy

2
@Izzy - DbModelBuilder คือ Entity Framework 6.0, ModelBuilder คือ EF Core พวกเขาเป็นแอสเซมบลีที่แตกต่างกันและในกรณีนี้คำถามเฉพาะสำหรับ EF Core
— Jason

29

ใน EF7 คุณจะแทนที่ OnModelCreating บนคลาส DbContext ที่คุณกำลังใช้งาน

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

23
ดังนั้นถ้าฉันมีการกำหนดค่าประเภทเอนทิตี 20 รายการฉันใส่ไว้ในวิธีการใหญ่วิธีเดียว
— Den

6
โดยค่าเริ่มต้นดูเหมือนว่าจะเป็นเช่นนั้น คุณสามารถสร้างคลาส FooMapper / FooModelBuilder ของคุณเองที่ขยายคลาสพื้นฐานและมีเมธอดที่คุณส่งผ่าน EntityBuilder <Foo> ที่พิมพ์ คุณยังสามารถใช้อินเทอร์เฟซการฉีดยาและการกำหนดค่า IConfiguration ใหม่เพื่อให้พวกเขาค้นพบ / เรียกหาคุณโดยอัตโนมัติหากคุณต้องการเป็นแฟนซี!
— Avi Cherry

1
ยินดีต้อนรับ การโหวตคำตอบ (และกระตุ้นให้ผู้ถามยอมรับ) จะดีกว่า!
— Avi Cherry

ฉันมักจะทำสิ่งนี้ :)
— Den

4
ลองใช้เครื่องมือฉีดพึ่งพาใหม่หรือไม่? สร้างIEntityMapperStrategyอินเทอร์เฟซด้วยvoid MapEntity(ModelBuilder, Type)ลายเซ็นและbool IsFor(Type). ใช้อินเทอร์เฟซกี่ครั้งหรือกี่ครั้งก็ได้ตามที่คุณต้องการ (เพื่อให้คุณสามารถสร้างคลาสที่สามารถแมปเอนทิตีมากกว่าหนึ่งเอนทิตีได้ถ้าคุณต้องการ) จากนั้นสร้างคลาสอื่น (ผู้ให้บริการกลยุทธ์) ที่ฉีดIEnumerableไฟล์IEntityMapperStrategies. ดูที่นี่ภายใต้ "ประเภทพิเศษ" ใส่เข้าไปในบริบทของคุณ
— Avi Cherry

22

กำลังใช้เบต้า 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>());
    }

3
ฉันลงเอยด้วยการทำเช่นนี้ ฉันตัดสินใจที่จะใช้วิธีการแบบคงที่แทนที่จะเป็นตัวสร้าง
— Matt Sanders

ฉันใช้วิธีนี้และจนถึงจุดนี้ฉันไม่มีปัญหาใด ๆ ยกเว้นเรื่องมรดก หากฉันต้องการสืบทอด AccountMap ในตัวอย่างของคุณเป็นบัญชีใหม่และเพิ่มคีย์สำรองวิธีใดที่ดีที่สุด
— chris

14

คุณสามารถใช้การไตร่ตรองเพื่อทำสิ่งต่างๆได้เช่นเดียวกับวิธีการทำงานใน EF6 โดยมีคลาสการทำแผนที่แยกกันสำหรับแต่ละเอนทิตี สิ่งนี้ใช้ได้ใน RC1 รอบสุดท้าย:

ขั้นแรกสร้างอินเทอร์เฟซสำหรับประเภทการทำแผนที่ของคุณ:

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

อ้างอิงDataContextและ.Whereใช้อะไร? ฉันสร้างโครงการแยกต่างหากสำหรับสิ่งนี้และดูเหมือนจะไม่พบข้อมูลอ้างอิง
— Ruchan

.Whereเป็นSystem.Linq, DataContextอยู่ในระดับที่รหัสถูกเพิ่ม (EF ของฉันDbContextImpl)
— Cocowalla

12

เนื่องจาก EF Core 2.2 คุณสามารถเพิ่มการกำหนดค่าทั้งหมด (คลาสซึ่งใช้อินเทอร์เฟซ IEntityTypeConfiguration) ในหนึ่งบรรทัดในเมธอด OnModelCreating ในคลาสซึ่งสืบทอดมาจากคลาส DbContext

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 การกำหนดค่าการแมปการตั้งค่าโดยใช้ 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);
    }
}

6

นี่คือสิ่งที่ฉันทำในโปรเจ็กต์ที่กำลังทำอยู่

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.Mapping.cs', Visual Studio จะพับไฟล์ในตัวสำรวจโซลูชัน เพื่อให้อยู่ภายใต้ไฟล์คลาสเอนทิตี


ขอบคุณสำหรับการแก้ปัญหาของคุณ ฉันจะเพิ่มประสิทธิภาพโค้ดโซลูชันของฉันเมื่อสิ้นสุดโครงการของฉัน ... ฉันตรวจสอบให้แน่ใจในอนาคต
— Miroslav Siska

ฉันสามารถสันนิษฐานได้ว่า 'IEntityTypeConfiguration <T>' เท่านั้นและConfigure(builder)ไม่มีอยู่ในปี 2559? ด้วยการเปลี่ยนสายไฟเล็กน้อยเพื่อชี้ไปที่ TypeConfiguration ไม่จำเป็นต้องมีอินเทอร์เฟซ 'พิเศษ'
— WernerCD

3

ฉันลงเอยด้วยวิธีนี้:

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

ฉันได้รับข้อผิดพลาดเวลาคอมไพล์: " Operator '! x.IsAbstract' ไม่สามารถใช้กับตัวถูกดำเนินการประเภท 'method group' " บน '! x.IsAbstract' (System.Type.IsAbstract) ใน ModelBuilderExtenions.GetMappingTypes () . ฉันต้องเพิ่มการอ้างอิงถึง mscorlib หรือไม่ ฉันจะทำเช่นนั้นกับโครงการ. NET Core 1.0 ได้อย่างไร
— RandyDaddis

สำหรับโปรเจ็กต์. net core (โดยใช้ netstandard) คุณต้องใช้ส่วนขยาย GetTypeInfo () ในเนมสเปซ System.Reflection ใช้เป็น x.GetTypeInfo () IsAbstract หรือ x.GetTypeInfo () GetInterfaces ()
— animalito maquina

ฉันใช้ส่วนหนึ่งของวิธีแก้ปัญหาของคุณกับฉันแล้วและมันก็ใช้ได้ดี ขอบคุณ!
— Diego Cotini

2

เพียงแค่ใช้ 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; }
}

1

ใน ef core เราต้องเพิ่ม IEntityTypeConfiguration แทน EntityTypeConfiguration ในกรณีนี้เราสามารถเข้าถึง DbContext modelBuilder ได้เต็มรูปแบบและเราสามารถใช้ fluent api ได้ แต่ใน ef core api นี้เป็นบิต litle ที่แตกต่างจากเวอร์ชันก่อนหน้า คุณสามารถดูรายละเอียดเพิ่มเติมเกี่ยวกับการกำหนดค่าโมเดล ef core ได้ที่

https://www.learnentityframeworkcore.com/configuration/fluent-api


1

ใน 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 });
        }
    }

ไม่ได้ผลสำหรับฉัน ข้อยกเว้น:Late bound operations cannot be performed on types or methods for which ContainsGenericParameters is true.
— Tohid

PS: พบวิธีแก้ปัญหา: &&! t.IsGenericType เพราะฉันมีคลาสพื้นฐานที่เป็นคลาสทั่วไป ( class EntityTypeConfigurationBase<TEntity> : IEntityTypeConfiguration<TEntity>) คุณไม่สามารถสร้างอินสแตนซ์ของคลาสพื้นฐานนี้ได้
— Tohid

0

ฉันถูกไหม?

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

ฉันสามารถผ่าน config:

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

    } 

คำตอบที่ยอมรับดูเหมือนจะดีกว่านี้ ทั้งสองมีผลข้างเคียงในทางลบเหมือนกันจากการมี OnModelCreating () ที่รกอย่างหนาแน่น แต่คำตอบที่ยอมรับนั้นไม่จำเป็นต้องมีคลาสตัวช่วยใด ๆ มีบางอย่างที่ฉันขาดหายไปที่คำตอบของคุณดีขึ้นหรือไม่?
— Sailing Judo

0

ฉันทำตามแนวทางที่คล้ายกันกับวิธีที่ 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>();           

    }

ด้วยวิธีนี้เรากำลังติดตามไฟล์ รูปแบบเดียวกับที่ใช้โดยวิธีการสร้างอื่น ๆ

คุณทำอะไร?


0

นี่คือปัญหาสำหรับการเพิ่มประสิทธิภาพใน repo EF7 Github: https://github.com/aspnet/EntityFramework/issues/2805

คุณสามารถติดตามปัญหาได้โดยตรงที่นั่นแม้ว่าปัญหาจะยังคงอยู่ในระบบค้างส่งโดยไม่มีลำดับความสำคัญ


ควรมีปัญหาเช่น "หยุดทำลายสิ่งที่ออกแบบมาดี"
— Kamil

0

ฉันมีโครงการที่อนุญาตให้คุณกำหนดค่าเอนทิตีภายนอก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 ของคุณคุณต้องบอก Entity Framework ว่าจะค้นหาคลาสคอนฟิกูเรชันทั้งหมดของคุณได้จากที่ใดเมื่อคุณกำหนดค่า DbContext ของคุณ

using StaticDotNet.EntityFrameworkCore.ModelConfiguration;

public void ConfigureServices(IServiceCollection services)
{
    Assembly[] assemblies = new Assembly[]
    {
        // Add your assembiles here.
    };

    services.AddDbContext<ExampleDbContext>( x => x
        .AddEntityTypeConfigurations( assemblies )
    );
}

นอกจากนี้ยังมีตัวเลือกสำหรับการเพิ่มการกำหนดค่าประเภทโดยใช้ผู้ให้บริการ repo มีเอกสารวิธีการใช้งานครบถ้วน

https://github.com/john-t-white/StaticDotNet.EntityFrameworkCore.ModelConfiguration


โปรดอย่าโพสต์คำตอบเดียวกันสำหรับคำถามหลายข้อ หากข้อมูลเดียวกันตอบคำถามทั้งสองคำถามได้จริงคำถามหนึ่งข้อ (โดยปกติจะเป็นคำถามที่ใหม่กว่า) ควรปิดเป็นคำถามที่ซ้ำกัน คุณสามารถระบุสิ่งนี้ได้โดยการลงคะแนนเพื่อปิดว่าเป็นรายการที่ซ้ำกันหรือหากคุณมีชื่อเสียงไม่เพียงพอให้ยกธงขึ้นเพื่อระบุว่าเป็นรายการที่ซ้ำกัน หรืออย่าลืมปรับแต่งคำตอบสำหรับคำถามนี้และอย่าวางคำตอบเดียวกันในหลาย ๆ ที่
— elixenide
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.