Code-First Entity Framework多态关系,如果一个派生类型包含另一个

时间:2016-02-27 04:55:06

标签: asp.net-mvc entity-framework entity-framework-6 data-modeling

在聚会规划应用中使用EF6 Code-First,我正在尝试使用Party属性(例如Attendees)为ICollection<???> Attendees实体建模,其中与会者可以是PersonFamily以及Family包含Person个实例的集合。

我在这里阅读了一系列有用的Code-First建模文章:http://weblogs.asp.net/manavi/associations-in-ef-4-1-code-first-part-1-introduction-and-basic-concepts。如果与会者为DogCat或其他一些相互排斥,不相关的类型,则这些文章中的建议是明确的。

但是对于PersonFamily之间可能彼此相关的实体集合进行建模的正确方法是什么?

编辑:我在这里要解决的主要问题是如何建模ICollection<???> Attendees实体的Party属性。具体而言,上面链接的文章给出了关于选择继承建模策略的建议(引用如下)。在我的用例中,一个派生类型(Family)包含来自另一个派生类型(Person)的实例。这是否表明我应该使用其中一种策略?或者这个事实与建模策略的选择无关?

  

表示继承有三种不同的方法   层次结构:

     
      
  • 每个层次结构表(TPH):通过对SQL模式进行非规范化来启用多态,并使用包含类型的类型鉴别器列   信息。
  •   
  • 每种类型的表(TPT):将“是”(继承)关系表示为“具有”(外键)关系。
  •   
  • 每个Concrete类的表(TPC):完全从SQL模式中丢弃多态和继承关系。
  •   
     

&LT;剪断&GT;

     

在我们讨论之前,我想强调一下   没有一个单一的“最佳策略适合所有场景”存在。如你所见,   每种方法都有各自的优点和缺点。这里   确定特定的最佳策略是一些经验法则   情形:

     
      
  • 如果您不需要多态关联或查询,请倾向于TPC - 换句话说,如果您从未或很少查询   BillingDetails,你没有与之关联的类   BillingDetail基类。我建议使用TPC(仅限)   您的类层次结构,通常不需要多态,以及   在将来修改基类时不太可能。

  •   
  • 如果确实需要多态关联或查询,子类声明的属性相对较少(特别是如果主要的话)   子类之间的差异在于他们的行为),倾向于TPH。   您的目标是最小化可空列的数量和   说服自己(和你的DBA)非规范化架构不会   从长远来看会产生问题。

  •   
  • 如果确实需要多态关联或查询,子类声明了许多属性(子类主要区别在于   他们持有的数据),倾向于TPT。或者,取决于宽度和深度   您的继承层次结构和可能的连接成本   工会,使用TPC。

  •   
     

默认情况下,仅针对简单问题选择TPH。更复杂   案例(或者当你被坚持使用的数据建模者推翻时   你应该应该考虑可空性约束和正常化的重要性   考虑TPT战略。但在那时,问自己是否   将继承重建为对象中的委托可能不是更好   模型(委托是一种使组合成为重用的强大方法   作为继承)。通常最好避免复杂的继承   与持久性或ORM无关的各种原因。 EF充当缓冲区   域和关系模型之间,但这并不意味着你   在设计类时可以忽略持久性问题。

1 个答案:

答案 0 :(得分:0)

你的模型看起来像这样:

 public class Family
{
    public int Id { get; set; }
    public string Name { get; set; }
public ICollection<Person> People { get; set; }

}
public class Person 
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public Family Family { get; set; }
}

并添加一些像这样的配置:

   HasRequired(row => row.Family).WithMany().HasForeignKey(row => row.FamilyId).WillCascadeOnDelete(false);