如何在每个层次结构(TPH)映射中共享公用列名称

我正在使用Entity Framework 4 CTP5代码第一种方法,我有一个每层次表(TPH)映射。 层次结构中的某些类具有共同的属性。

public class BaseType { public int Id { get; set; } } public class A : BaseType { public string Customer { get; set; } public string Order { get; set; } } public class B : BaseType { public string Customer { get; set; } public string Article { get; set; } } public class C : BaseType { public string Article { get; set; } public string Manufacturer { get; set; } } 

默认约定将其映射到以下列:

  • ID
  • 第1条
  • 第二条
  • customer1表
  • 顾客2
  • 生产厂家
  • 订购
  • 类型

我想让EF4共享公共属性,最终得到以下结果:

  • ID
  • 文章
  • 顾客
  • 生产厂家
  • 订购
  • 类型

除了减少列数之外,这还具有能够基于文章搜索记录的优点,而无需知道哪些类型具有Article属性。

我尝试将每个公共属性映射到同一列:

 modelBuilder.Entity().Property(n => n.Article).HasColumnName("Article"); modelBuilder.Entity().Property(n => n.Article).HasColumnName("Article"); 

但是这引起了以下exception:

指定的架构无效。 错误:(36,6):错误0019:类型中的每个属性名称必须是唯一的。 已定义属性名称“文章”。

有谁知道如何绕过这个validation规则?

没有解决方法可以绕过此validation。 在TPH中,列要么属于所有子级inheritance的基类,要么专用于子类。 您不能指示EF将其映射到您的两个孩子,而不是另一个孩子。 尝试这样做(例如,在A.Customer和B.Customer上放置[Column(Name = "Customer")]将导致带有以下消息的MetadataException

指定的架构无效。 错误:(10,6):错误0019:类型中的每个属性名称必须是唯一的。 已定义属性名称“客户”。

TPH解决方案:

解决此问题的一种方法是将CustomerArticle属性提升到基类:

 public class BaseType { public int Id { get; set; } public string Customer { get; set; } public string Article { get; set; } } public class A : BaseType { public string Order { get; set; } } public class B : BaseType { } public class C : BaseType { public string Manufacturer { get; set; } } 

这导致所需的架构:

替代文字

TPT解决方案(推荐):

也就是说,我建议考虑使用每种类型的表 (TPT),因为它更适合您的场景:

 public class BaseType { public int Id { get; set; } } public class A : BaseType { [Column(Name = "Customer")] public string Customer { get; set; } public string Order { get; set; } } public class B : BaseType { [Column(Name = "Customer")] public string Customer { get; set; } [Column(Name = "Article")] public string Article { get; set; } } public class C : BaseType { [Column(Name="Article")] public string Article { get; set; } public string Manufacturer { get; set; } } public class MyContext : DbContext { public DbSet BaseTypes { get; set; } protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity().ToTable("BaseType"); modelBuilder.Entity().ToTable("A"); modelBuilder.Entity().ToTable("C"); modelBuilder.Entity().ToTable("B"); } } 

替代文字

对于任何遇到此问题的人,现在已经修复了EF6: entity framework – Codeplex