Course contentsShow
← C#
Lesson 1043 of 1,90810. Entity Framework Core ModelingFree lesson

Table-per-Hierarchy Inheritance

Implement entity inheritance strategies using discriminator columns in a shared table.

In this lesson, you will learn how to map an entire class inheritance hierarchy into a single database table using Entity Framework Core's "Table-per-Hierarchy" (TPH) strategy.

The Concept

When you have a base class and several derived classes (e.g., Payment as the base, with CreditCardPayment and PayPalPayment as derivatives), you don't always need separate tables for each. TPH allows you to store all these objects in one table. To differentiate between the types at runtime, EF Core adds a Discriminator column to the table. This column acts as a label, telling the database which specific subclass a row belongs to.

Implementation

To implement this, you simply define your classes as usual and ensure your DbContext understands the relationship. By default, EF Core uses TPH if it detects an inheritance hierarchy, but we can be explicit using the Fluent API.

public abstract class Payment {
    public int Id { get; set; }
    public decimal Amount { get; set; }
}

public class CreditCardPayment : Payment {
    public string CardNumber { get; set; }
}

public class PayPalPayment : Payment {
    public string Email { get; set; }
}

// In your DbContext
protected override void OnModelCreating(ModelBuilder modelBuilder) {
    modelBuilder.Entity<Payment>()
        .HasDiscriminator<string>("payment_type")
        .HasValue<CreditCardPayment>("credit_card")
        .HasValue<PayPalPayment>("paypal");
}

Why Use TPH?

The primary benefit of TPH is performance. Because all related data lives in one table, you avoid expensive JOIN operations when querying base types or retrieving polymorphic collections.

When you query the base class Payment, EF Core automatically adds a WHERE clause to filter by the discriminator column, ensuring you only retrieve the expected data. If a specific property (like CardNumber) only exists on one subclass, EF Core simply leaves that column as NULL for other types in the table. This makes it a highly efficient way to manage inheritance, provided your subclasses don't have too many unique properties that would result in a table filled with empty NULL cells.

Key Takeaway: Table-per-Hierarchy uses a single table and a discriminator column to map an entire inheritance tree, prioritizing high-performance queries over strict database normalization.