如何在每个层次结构(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解决方案:
解决此问题的一种方法是将Customer
和Article
属性提升到基类:
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