实体框架 - 如何避免类层次结构中的TPC

时间:2015-12-06 21:29:25

标签: c# entity-framework database-design ef-code-first

在我的业务领域,我有两个实体,作为对象,根据它们公开的属性定义层次关系,但在数据库级别它们是非常不同的。

具体来说,我所拥有的是一个Image类,它定义了属性A和B(在Id旁边),以及几个简单的方法。 然后我有一个Thumbnail类,它与Image完全相同。

在OOP透视图中,使Thumbnail从Image继承是合乎逻辑的。但是,在Db级别,这两个实体在一个重要细节上有所不同: 图像将FK声明为另一个表而缩略图不是。

实际上,Image定义了Product(例如)可以拥有的图像集(Many-to-One),但Thumbnail定义了同一产品可以拥有的唯一缩略图(One-or-Zero-to-One) 。在这种情况下,缩略图不会出现在图像集中。

因此,在数据库中,Image表应该有列A,B,Id和FK到Product,而Thumbnail表应该只有列A,B和Id(也是FK到Product)。 / p>

如果我使用EF Code First对此进行建模,最好(尽可能)它为Image生成一个表,然后为Thumbnail生成一个表,在Image和Thumbnail之间生成一对一或从零到一的关联。这种关联是我试图避免的,因为添加缩略图我还必须将其添加为图像,然后设置FK,这是不可能的,因为它没有。

如果我明确指定生成TPC,那么它不允许我在Product和Image之间建立关联,因为关联只能在大多数派生类型中定义。

你有什么想法吗?

1 个答案:

答案 0 :(得分:2)

您需要配置实体,以便他们使用Mapping the Table-Per-Concrete Class (TPC) Inheritance

  

在TPC映射方案中,层次结构中的所有非抽象类型都映射到各个表。映射到派生类的表与映射到数据库中的基类的表没有关系。类的所有属性(包括继承的属性)都映射到相应表的列。

这是使用TPC ::

的可能配置的示例
modelBuilder.Entity<Image>() 
  .Property(c => c.ImageID) 
  .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None); 

modelBuilder.Entity<ThumbNail>().Map(m => 
{ 
    m.MapInheritedProperties(); 
    m.ToTable("Thumbnails");
}); 

为了您的特定目的,您必须对其进行微调。例如,使用以下内容排除FK属性:

modelBuilder.Entity<Thumbnail>().Ignore(p => p.FkProperty);