entity framework:如何避免表中的Discriminator列?

我有使用Entity Framework Code First方法创建的下表。

  1. 如何修改C#代码,以便不在数据库中创建不需要的Discriminator列? 是否有任何属性可以实现这一目标?
  2. 如何将外键列名称设为“PaymentID”而不是“Payment_ PaymentID”? 是否有任何属性可以实现这一目标?

注意:EntityFramework.dll的运行时版本是v4.0.30XXX

在此处输入图像描述

public abstract class PaymentComponent { public int PaymentComponentID { get; set; } public int MyValue { get; set; } public string MyType { get; set; } public abstract int GetEffectiveValue(); } public partial class GiftCouponPayment : PaymentComponent { public override int GetEffectiveValue() { if (MyValue < 2000) { return 0; } return MyValue; } } public partial class ClubCardPayment : PaymentComponent { public override int GetEffectiveValue() { return MyValue; } } public partial class Payment { public int PaymentID { get; set; } public List PaymentComponents { get; set; } public DateTime PayedTime { get; set; } } //System.Data.Entity.DbContext is from EntityFramework.dll public class NerdDinners : System.Data.Entity.DbContext { public NerdDinners(string connString): base(connString) { } protected override void OnModelCreating(DbModelBuilder modelbuilder) { modelbuilder.Conventions.Remove(); } public DbSet GiftCouponPayments { get; set; } public DbSet ClubCardPayments { get; set; } public DbSet Payments { get; set; } } 

客户

  static void Main(string[] args) { string connectionstring = "Data Source=.;Initial Catalog=NerdDinners;Integrated Security=True;Connect Timeout=30"; using (var db = new NerdDinners(connectionstring)) { GiftCouponPayment giftCouponPayment = new GiftCouponPayment(); giftCouponPayment.MyValue=250; giftCouponPayment.MyType = "GiftCouponPayment"; ClubCardPayment clubCardPayment = new ClubCardPayment(); clubCardPayment.MyValue = 5000; clubCardPayment.MyType = "ClubCardPayment"; List comps = new List(); comps.Add(giftCouponPayment); comps.Add(clubCardPayment); var payment = new Payment { PaymentComponents = comps, PayedTime=DateTime.Now }; db.Payments.Add(payment); int recordsAffected = db.SaveChanges(); } } 

TPHinheritance需要特殊列,用于标识实体的类型。 默认情况下,此列称为Discriminator ,包含派生实体的名称。 您可以使用Fluent-API定义不同的列名和不同的值。 您也可以直接使用MyType列,因为它实际上是一个鉴别器,但在这种情况下,您的实体中不能包含该列(列只能映射一次,如果您将其用作鉴别器,则它已被视为映射)。

可以使用Fluent-API再次控制外键列的名称:

 protected override void OnModelCreating(DbModelBuilder modelbuilder) { modelbuilder.Conventions.Remove(); // Example of controlling TPH iheritance: modelBuilder.Entity() .Map(m => m.Requires("MyType").HasValue("G")) .Map(m => m.Requires("MyType").HasValue("C")); // Example of controlling Foreign key: modelBuilder.Entity() .HasMany(p => p.PaymentComponents) .WithRequired() .Map(m => m.MapKey("PaymentId")); } 

如果属性不会映射到列,则添加属性[NotMapped]。

也可以使用每种类型的表(TPT)。

http://weblogs.asp.net/manavi/inheritance-mapping-strategies-with-entity-framework-code-first-ctp5-part-2-table-per-type-tpt

每种类型的表(TPT)

每个类型的表是关于将inheritance关系表示为关系外键关联。 声明持久属性的每个类/子类(包括抽象类)都有自己的表。 子类表仅包含每个非inheritance属性的列(子类本身声明的每个属性)以及主键,该主键也是基类表的外键。

在EF Code First中实施TPT

我们可以简单地通过在子类上放置Table属性来指定映射的表名来创建TPT映射(Table属性是一个新的数据注释,并且已添加到CTP5中的System.ComponentModel.DataAnnotations命名空间。

如果您更喜欢流畅的API,那么您可以使用ToTable()方法创建TPT映射:

 protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity().ToTable("BankAccounts"); modelBuilder.Entity().ToTable("CreditCards"); } 

在使用子类时,需要使用Discriminator列来区分每种类型的子类。

由于“GiftCouponPayment”和“ClubCardPayment”都来自“PaymentComponent”,因此EF不会使用单独的表,而是需要该列。 如果你想要一个不同的行为,你必须覆盖默认的表访问并将字段映射到你的类(我认为你不想这样做)不确定是否有一个简单的方法来实现。 从实体开始,我知道有一种方法可以通过模板创建表格。
外键列名称也是如此。 EF使用这种方式为key / foreignkey名称创建名称。 如果你想按照你喜欢的方式格式化表格,你必须自己完成所有这些,这就导致了为什么要使用EF的问题。
除了化妆品之外,你有什么理由想要这样做吗?

用于删除Discriminator列并将名为PaymentId的列作为鉴别器的示例代码,因此解决了您的问题。 基于Microsofts Fluent Api原始文档。

https://msdn.microsoft.com/en-us/library/jj591617%28v=vs.113%29.aspx?f=255&MSPPError=-2147217396

 public enum MyEnum { Value1, Value2 } public class MyBaseClass { [NotMapped] public MyEnum PaymentId { get; protected set; } } public class DerivedOne: MyBaseClass { public DerivedOne() { PaymentId = MyEnum.Value1; } } public class DerivedTwo: MyBaseClass { public DerivedTwo() { PaymentId = MyEnum.Value2; } } public class MyDbContext : DbContext { DbSet MyBaseClass { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity() .Map(x => x.Requires("PaymentId").HasValue((int)PaymentId.Value1)) .Map(x => x.Requires("PaymentId").HasValue((int)PaymentId.Value2)); } } 

为了避免表中的Discriminator列,您只需要在派生类上添加注释[NotMapped]。