我可以使用每个类型的表映射指定一个鉴别器列吗?

时间:2011-08-22 00:54:50

标签: entity-framework-4.1

我有一个类层次结构,我希望使用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”列,这是不正确的。我已经告诉它“代码”列在“事件”表中。

这甚至可能吗?我可以将鉴别器列的使用与每个类型的映射结合起来吗?

2 个答案:

答案 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();
    }
}