使用实体框架中的自定义惯例控制列映射6

问题描述:

我有一个类TypeEntity,它将充当几十个实体的基类。我正在使用TPC,所以我需要将基类中的所有属性映射到具有具体类的名称的表,并将Key字段设置为数据库生成。使用实体框架中的自定义惯例控制列映射6

目前我有EntityTypeConfiguration的,看起来像这样每个实体类型这样做:

class LineItemType : EntityTypeConfiguration<Models.LineItemType> 
{ 
    public LineItemType() 
    { 
     this.Property(e => e.Key) 
      .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 

     this.Map(e => e.MapInheritedProperties() 
         .ToTable(nameof(LineItemType))); 
    } 
} 

这工作得很好,但很重复。我必须记得为从TypeEntity继承的每种类型创建一个配置类,设置密钥并映射继承的属性。这似乎是一个自定义Convention的理想情况。


我创建了一个TypeEntityTpcConventionConvention如下:

class TypeEntityTpcConvention : Convention 
{ 
    public TypeEntityTpcConvention() 
    { 
     this.Types<TypeEntity>() 
      .Configure(e => e.Property(p => p.Key) 
          .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity)); 
    } 
} 

其中一期工程设置Key为生成的数据库,但我找不到任何办法从里面约定的访问属性表映射。


理想情况下,我希望这样的事情:

this.Types<TypeEntity>() 
    .Configure(e => e.MapInheritedProperties() 
    .ToTable(e.ClrType.Name)); 

甚至一个电话这样对于需要映射每个属性:

this.Types<TypeEntity>() 
    .Configure(e => e.Property(p=>p.Key) 
        .ToTable(e.ClrType.Name)); 

均未似乎存在。有没有什么办法可以控制Convention内部的物业映射?


经过一些额外的研究,它看起来像有可作为IStoreModelConventionIConceptualModelConvention更先进的会议场所,但有用的文档,如何使用这些严重缺乏。经过几个小时用断点和观察窗口戳穿它们,我还没有想出如何使用这些接口来控制列映射。


我目前的解决方案是使用反射来发现,从TypeEntityOnModelCreating继承了所有类型和属性映射到正确的表。这是有效的,但如果可能的话,我宁愿使用一个约定,因为这看起来好像是为约定制定的类型。我觉得我失去了一些明显的东西。

+0

的问题是没有得到类的名称,它是'.ToTable'(或其他允许我将属性重定向到不同表格的东西)似乎不存在于“Convention”的上下文中。 –

+0

啊..我误解了。我将删除评论。 –

+0

我有一个解决方案。这不完全是一个惯例,但它确实会自动应用于您指定的所有类型(即,您不必为每个实体添加一行新的配置)。如果你有兴趣,我可以发布它。 –

据我所见,你可以在你的DbContextOnModelCreating方法中编写类型配置,它与你在问题中已经提到的代码非常相似。

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

    modelBuilder.Types<TypeEntity>().Configure(c => 
    { 
     c.HasKey(p => p.Key); 
     // probably not needed, but won't do any harm 
     c.Property(p => p.Key).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 
     c.ToTable(c.ClrType.Name); 
    }); 
} 

如果此方法有任何问题,请告诉我,我将重新访问该主题。

编辑:

完全相同的原理可以约定适用:

class TypeEntityConvention : Convention 
{ 
    public TypeEntityConvention() 
    { 
     this.Types<TypeEntity>().Configure(c => 
     { 
      c.HasKey(p => p.Key); 
      c.Property(p => p.Key).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 
      c.ToTable(c.ClrType.Name); 
     }); 
    } 
} 

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

    modelBuilder.Conventions.Add<TypeEntityConvention>(); 
} 
+0

这也是我的解决方案。不是一个约定,但它是通用的,没有反射。 –

+0

我喜欢你的解决方案比我目前使用的解决方案更好,但这真的感觉像'Convention'应该能够处理的东西。在这一点上,我有一个可行的解决方案,这只是我的愿望,要学会如何有效地使用约定,这就是现在要解决这个问题。 –

+0

@BradleyUffner看到我的更新。 – grek40