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.