当EF6

时间:2016-05-02 15:38:18

标签: c# inheritance entity-framework-6 table-per-hierarchy tph

我周末花了很多时间试图弄明白这一点。

我有一个包含Subscription表的现有数据库,我想使用TPH继承策略映射到我域中的实体。

订阅有几种类型,每种类型都有自己的特点,因此需要继承。这是域名的简化版本:

public class Subscription
{
    public int CustomerID { get; set; }
    public virtual Customer Customer { get; set; }
    public int SubscriptionID { get; set; }
    public string Name { get; set; }
}
public class BookSubscription:Subscription
{
    public string Book { get; set; }
}
public class TVSubscription : Subscription
{
    public string Channel { get; set; }
}

这些实体在上下文中映射如下:

public DbSet<Customer> Customers { get; set; }
public DbSet<Subscription> Subscriptions { get; set; }
public DbSet<TVSubscription> TVSubscriptions { get; set; }

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    modelBuilder.Entity<Customer>().ToTable("tblCustomer");
    modelBuilder.Entity<Customer>().HasKey(t => t.CustomerID);

    modelBuilder.Entity<Subscription>()
            .Map<Subscription>(m =>
            {
                m.ToTable("tblSubscription");
                m.Requires("ServiceTypeId").HasValue(1);
            })
             .Map<TVSubscription>(m =>
             {
                 m.Requires("ServiceTypeId").HasValue(20);
             })
            .Map<BookSubscription>(m =>
            {
                m.Requires("ServiceTypeId").HasValue(5);
            }
            );
    modelBuilder.Entity<Subscription>().HasKey(s => s.SubscriptionID);

    base.OnModelCreating(modelBuilder);
}

正如所料,当查询任何派生类的上下文时,EF使用ServiceTypeId作为鉴别器正确构造查询。当我尝试在Customer实体中包含派生类时出现问题。这有效:

public class Customer
{
    public int CustomerID { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Subscription> Subscriptions{ get; set; }      
}

这不起作用:

public class Customer
{
    public int CustomerID { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Subscription> Subscriptions{ get; set; }
    public virtual ICollection<TVSubscription> TvSubscriptions { get; set; }
}

这两个都没有:

public class Customer
{
    public int CustomerID { get; set; }
    public string Name { get; set; }

    public virtual ICollection<TVSubscription> TvSubscriptions { get; set; }
}

当我检查分析器时,我可以看到,在这两种情况下,EF都会添加_id后缀,并尝试查询除customerID之外的不存在的customer_id列。我试图为派生类型显式映射外键,但EF当时抱怨:

  

外键组件&#39; CustomerID&#39;不属于'TVSubscription&#39;类型的声明属性。验证它是否未从模型中明确排除,并且它是有效的原始属性。

CustomerID在派生类中没有位置,但即使我尝试在那里移动它也不起作用(我怀疑因为EF然后尝试使用另一种继承策略进行映射)。

现在,我知道我可以使用这样的东西:

public IEnumerable<TVSubscription> TvSubscriptions
{
    get { return Subscriptions.OfType<TVSubscription>(); }
}

但是,使用此方法,EF会查询db以获取整个订阅集,然后在本地过滤它以仅返回TVSubscriptions。这肯定不理想,因为客户可以拥有数百个订阅,并且我希望EF只能查询并返回特定类型的订阅 - 就像我在使用dbContext时已经做的那样。

所以问题是,如何在Customer类中包含TVSubscriptions列表并且只对那些人进行EF查询?

如果无法做到这一点,有人可以解释当我向Customer实体添加派生类集合时EF正在做出什么样的假设。

0 个答案:

没有答案