我有一个类层次结构,我希望使用Entity Framework 4.1 Code First映射到多个表。这就像每个类型的表(TPT),但我也想要一个discrimator列。
层次结构类似于:
public class Event
{
public Guid Id { get; set; }
public string Code { get; set; } // discriminator
public DateTime Date { get; set; }
}
public class Party : Event
{
public int AttendeeCount { get; set; }
}
public class BirthdayParty : Party
{
public int Age { get; set; }
}
public class WeddingParty : Party
{
public string Surname { get; set; }
}
这是一个非常弱的例子,但我希望它有意义。将有一个“事件”表,一个“缔约方”表格和每种派对的表格。但是,鉴别栏(“代码”)对每种事件都有一个已知值,如生日派对的“BIRTH”或婚礼派对的“WEDDING”。
我的想法是,如果我在给定日期仅查询生日派对,EF会知道将Code = 'BIRTH'
添加到我的查询中,而不是做一堆UNION和JOIN来计算出它需要哪些行。< / p>
我映射我这样的最低级别的课程:
var bd = modelBuilder.Entity<BirthdayParty>();
bd.ToTable("BirthdayParties");
bd.Property(p => p.Age).HasColumnName("BirthdayAge");
我现在需要以某种方式指定鉴别器值。我试过这个:
modelBuilder.Entity<Event>().Map<BirthdayParty>(cfg =>
{
cfg.Requires("Code").HasValue("BIRTH");
});
...但是抱怨我没有在Map
的调用中指定表名。所以我尝试将ToTable
电话移到那里:
var bd = modelBuilder.Entity<BirthdayParty>();
bd.Property(p => p.Age).HasColumnName("BirthdayAge");
modelBuilder.Entity<Event>().Map<BirthdayParty>(cfg =>
{
cfg.Requires("Code").HasValue("BIRTH");
cfg.ToTable("BirthdayParties");
});
...现在它认为我想要“BirthdayParties”表中的“Code”列,这是不正确的。我已经告诉它“代码”列在“事件”表中。
这甚至可能吗?我可以将鉴别器列的使用与每个类型的映射结合起来吗?
答案 0 :(得分:8)
不幸的是,这不受支持。 Discriminator列只能在TPH中使用。 TPT通过映射表来区分实体类型,并且它总是产生那些可怕的查询。它可能是一个很好的功能,所以也许Data UserVoice上的建议会使它有一天实现。
<强>更新强>
对于标题为“Discriminator column support in TPT inheritance”的用户语音已有建议。
答案 1 :(得分:0)
我在SaveChanges上做了一个覆盖来完成类似的事情。我只是在名为Descriminator的抽象类中添加了一个属性,并在任何时候添加新内容的基础上根据Concrete Class Name设置它。
public class MyContext : DbContext
{
public override int SaveChanges()
{
foreach (var item in ChangeTracker.Entries().Where(x=>x.Entity is MyAbstractClass && x.State == EntityState.Added))
{
((MyAbstractClass)item.Entity).Descriminator = item.Entity.GetType().Name;
}
return base.SaveChanges();
}
}