Entity Framework 继承关系(TPH)
Entity Framework有三种处理类之间继承关系的方法,现在我们将逐一介绍这三种处理方法。
1.Table Per Hierarchy(TPH): 只建立一个表,把基类和子类中的所有属性都映射为表中的列。
2.Table Per Type(TPT): 为基类和每个子类建立一个表,每个与子类对应的表中只包含主键以及子类特有的属性对应的列。
3.Table Per Concrete Type(TPC): 为每个子类建立一个表,每个与子类对应的表中包含基类的属性对应的列和子类特有属性对应的列。
在TPH方式中,Entity Framework把基类和所有子类建立在一个表中,基类和子类中的所有属性都映射一列。Entity Framework默认在这个表中建立一个叫做Discriminator(意为“辨别者”,是不是很形象?)的列,类型是nvarchar,长度是128。在存储基类或子类的时候,把类名作为Discriminator列的值。
(1)实体类
1 /// <summary> 2 /// 交易记录 3 /// </summary> 4 public abstract class TransRecord 5 { 6 /// <summary> 7 /// Id 8 /// </summary> 9 public int Id { get; set; } 10 11 /// <summary> 12 /// 交易金额(单位:分) 13 /// </summary> 14 public long Amount { get; set; } 15 16 /// <summary> 17 /// 交易时间 18 /// </summary> 19 public DateTime DateTime { get; set; } 20 } 21 22 /// <summary> 23 /// 银联卡交易记录 24 /// </summary> 25 public class UnionPayTransRecord : TransRecord 26 { 27 /// <summary> 28 /// 银联卡卡号 29 /// </summary> 30 public string CardNo { get; set; } 31 32 /// <summary> 33 /// 交易号 34 /// </summary> 35 public string TransNo { get; set; } 36 } 37 38 /// <summary> 39 /// 会员卡交易记录 40 /// </summary> 41 public class MemberCardTransRecord : TransRecord 42 { 43 /// <summary> 44 /// 账号 45 /// </summary> 46 public string Account { get; set; } 47 }
(2)映射
1 public class TransRecordMap : EntityTypeConfiguration<TransRecord> 2 { 3 public TransRecordMap() 4 { 5 this.ToTable("TransRecord"); 6 7 this.HasKey(p => p.Id); 8 9 this.Property(p => p.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity); 10 this.Property(p => p.Amount).IsRequired(); 11 this.Property(p => p.DateTime).IsRequired(); 12 } 13 } 14 15 public class UnionPayTransRecordMap : EntityTypeConfiguration<UnionPayTransRecord> 16 { 17 public UnionPayTransRecordMap() 18 { 19 this.Property(p => p.CardNo).IsRequired().HasMaxLength(31); 20 this.Property(p => p.TransNo).IsRequired().HasMaxLength(31); 21 } 22 } 23 24 public class MemberCardTransRecordMap : EntityTypeConfiguration<MemberCardTransRecord> 25 { 26 public MemberCardTransRecordMap() 27 { 28 this.Property(p => p.Account).IsRequired().HasMaxLength(31); 29 } 30 }
(3)DbContext
1 public class ConsAppContext : DbContext 2 { 3 public IDbSet<TransRecord> TransRecrods { get; set; } 4 5 protected override void OnModelCreating(DbModelBuilder modelBuilder) 6 { 7 modelBuilder.Configurations.Add(new UnionPayTransRecordMap()); 8 modelBuilder.Configurations.Add(new MemberCardTransRecordMap()); 9 base.OnModelCreating(modelBuilder); 10 } 11 }
(4)生成效果
(5)测试及其结果
using (ConsAppContext context = new ConsAppContext()) { TransRecord t1 = new UnionPayTransRecord() { Amount = 1000, DateTime = DateTime.Now, CardNo = "12345678900x", TransNo = "123456789" }; TransRecord t2 = new MemberCardTransRecord() { Amount = 2000, DateTime = DateTime.Now, Account = "member-account" }; context.TransRecrods.Add(t1); context.TransRecrods.Add(t2); context.SaveChanges(); }