继承映射策略的三种策略
There are following three different approaches to represent an inheritance hierarchy in Code First:
- Table per Hierarchy (TPH): This approach suggests one table for entire class inheritance hierarchy. Table includes discriminator column which distinguish between inheritance classes. This is a default inheritance mapping strategy in Entity Framework.
- Table per Type (TPT): This approach suggests seperate table for each domain class.
- Table per Concrete class (TPC): This approach suggests one table for one concrete class, but not for the abstract class. So if you inherit the abstract class in multiple concrete classes then the properties of the abstract class will be part of each table of concrete class.
Code First 有以下三种不同的方法来表示继承层次结构:
- 每个层次结构一张表 (TPH): 这种方法表明,为整个类继承层次结构一个表。表包括鉴别器列(discriminator )的区分继承类。这是在实体框架中的默认继承映射策略。
- 每个类型一张表 (TPT): 这种方法显示单独的表中为每个域类。
- 每个具体类 一张表(TPC) : 这种方法显示一个表为一个具体的类,而不是抽象类。因此如果你继承的抽象类在多个具体的类然后抽象类的属性中将每个表具体类的一部分。
----------------------------------------------------------------------------
---------------------------------------------------
三种策略的适用场景
I want to emphasize that there is no one single "best strategy fits all scenarios" exists. As you saw, each of the approaches have their own advantages and drawbacks. Here are some rules of thumb to identify the best strategy in a particular scenario:
- If you don’t require polymorphic associations or queries, lean toward TPC—in other words, if you never or rarely query for BillingDetails and you have no class that has an association to BillingDetail base class. I recommend TPC (only) for the top level of your class hierarchy, where polymorphism isn’t usually required, and when modification of the base class in the future is unlikely.
- If you do require polymorphic associations or queries, and subclasses declare relatively few properties (particularly if the main difference between subclasses is in their behavior), lean toward TPH. Your goal is to minimize the number of nullable columns and to convince yourself (and your DBA) that a denormalized schema won’t create problems in the long run.
- If you do require polymorphic associations or queries, and subclasses declare many properties (subclasses differ mainly by the data they hold), lean toward TPT. Or, depending on the width and depth of your inheritance hierarchy and the possible cost of joins versus unions, use TPC.
By default, choose TPH only for simple problems. For more complex cases (or when you’re overruled by a data modeler insisting on the importance of nullability constraints and normalization), you should consider the TPT strategy. But at that point, ask yourself whether it may not be better to remodel inheritance as delegation in the object model (delegation is a way of making composition as powerful for reuse as inheritance). Complex inheritance is often best avoided for all sorts of reasons unrelated to persistence or ORM. EF acts as a buffer between the domain and relational models, but that doesn’t mean you can ignore persistence concerns when designing your classes.
我想强调的是没有一单"最佳策略适合所有场景"存在。正如你所看到的每个方法有自己的优点和缺点。以下是一些经验法则来确定在特定的情况下最好的策略:
- 如果你不需要多态关联或查询,倾向于 TPC — — 换句话说,如果你从来没有或很少查询 BillingDetails 和你没有类关联 BillingDetail 基类。我推荐 TPC (仅限于) 您的类层次结构的顶层多态性并不是经常需要的而且将来也不太可能修改基类。
- 如果您需要多态关联或查询,并子类相对定义了几个属性 (特别是如果子类之间的主要区别是在他们的行为),倾向于 TPH。你的目标是尽量减少的可以为 null 的列数,并说服自己 (和您的 DBA) 非规范化的架构在长期内不会产生问题。
- 如果您需要使用多态关联或查询,并且子类(主要由它们拥有的数据不同的子类)定义了很多属性,倾向于 TPT。或者,如果考虑到继承层次结构的宽度和深度和Joins与Unions的可能产生的成本,使用 TPC。
默认情况下,选择 TPH 仅为简单的问题。对于更复杂的情况下 (或当你正在推翻由数据建模者坚持的为空性约束和归一化的重要性),你应该考虑 TPT 战略。但在这一点上,问一问自己,是否它可以用delegation 修改下对象模型中的继承 (代表团是作文一样强大的复用作为继承的一种方式)。复杂的继承通常最好能够通过许多与持久化或 ORM 无关的原因避免。虽然EF 充当域和关系模型之间的缓冲,但这并不意味着设计您的类时,您可以忽略关注持久化的内容。
参考
- Inheritance with EF Code First: Table per Hierarchy (TPH)
- Inheritance with EF Code First: Table per Type (TPT)
- Inheritance with EF Code First: Table per Concrete class (TPC)