[Person]
PersonId [PK]
// other common fields that apply to ALL types of Person.
[Parent]
PersonId [PK, FK]
CityUtilityId [FK]
// other parent-specific fields.
[Child]
PersonId [PK, FK]
ParentPersonId [FK] (To Parent, not Person)
// other child-specific fields.
1条答案
按热度按时间798qvoo81#
EF同时支持每个层次结构的表(TPH)和每个具体类型的表(TPT),因此只要使用模式,您就可以选择。虽然父母和孩子都是一个人,但他们都有各自的特点。其中之一是,只有父母才能分配城市公用事业,其他的是孩子只能与父母相关联。(父级不能引用另一个父级作为子级,或者说子级不能引用另一个子级作为父级。)在单个表中处理所有这些场景的是一个TPH结构,它依赖于应用程序代码要强制执行的隐式规则,并为应用于其中一个或另一个的数据产生大量可为空的引用和字段。
只要有可能,我建议使用TPT结构,并使关系更加明确。这样做的好处是不需要完全依赖应用程序代码来确保关系和“可选性与必需性”在数据库级别强制执行。
这将包含类似以下内容:
这样,如果父项或子项具有必填或可选字段,则可以将它们放入各自的表中,并具有相应的空能力。另一种方法是,该字段始终为空,并由应用程序来确保强制执行其中之一的所需性质。DB将可以在任何时候错误地进入完全无效状态,而不会有任何抱怨。
在开发社区中,最小化表数仍然很有吸引力,这在很大程度上源于驱动器空间昂贵和模式成本$$的时代,因此将类似的数据合并到一个表中可能是有意义的。然而,在关系方面,它仍然存在重大缺陷。对于现代数据库,我认为只组合有效相同的内容并使用TPT进行继承或使用组合总是更好。
合成的一个例子就是具有状态的订单。该状态可能已交付,并且可能存在我们希望在交付订单时记录的详细信息。(签署等)这些字段可以是Order表上的Null字段,但它们仅适用于已交付的订单,在所有其他情况下将为Null。相反,拥有一个像OrderDeliveryDetails/w这样的表,它与Order是一对一的关系,这是在交付订单时创建的。(如果订单因任何原因从已交付状态更改为另一状态,则会删除/使其处于非活动状态。)