Entity Framework Core Mastery

Table-per-Hierarchy (TPH) Inheritance

1 Views Updated 5/4/2026

Table-per-Hierarchy (TPH) Inheritance

In Object-Oriented C#, Inheritance is a fundamental concept (e.g., Dog inherits from Animal). However, SQL Databases inherently do not support inheritance. EF Core bridges this gap securely using three distinct patterns, the most performant and default of which is Table-per-Hierarchy (TPH).

1. Modeling the C# Inheritance

Imagine a billing system where you sell both Physical Products and Digital Subscriptions. They share common traits (Price, Name) but possess unique traits.

public abstract class Product 
{
    public int Id { get; set; }
    public string Name { get; set; }
    public decimal Price { get; set; }
}

public class Book : Product 
{
    public decimal ShippingWeightKb { get; set; }
}

public class SoftwareLicense : Product 
{
    public string DownloadUrl { get; set; }
}

2. How TPH Works (The Discriminator Column)

By default, if you include these classes in your DbContext, EF Core will generate exactly ONE physical SQL Table named Products containing ALL the columns from EVERY subclass.

Id Discriminator (Auto-Generated) Name Price ShippingWeightKb DownloadUrl
1 "Book" C# Mastery 35.00 1500.5 NULL
2 "SoftwareLicense" Visual Studio 99.00 NULL "https://..."

EF Core uses the hidden Discriminator string column to figure out which C# subclass to instantiate when you run _context.Products.ToList()!

3. Customizing the Discriminator (Fluent API)

Storing the raw C# class name ("SoftwareLicense") as a string is brittle. If you rename the C# class later, your entire database breaks. We can configure TPH to use integers instead of class names.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Product>()
        // Override the default Discriminator to be an Integer
        .HasDiscriminator<int>("ProductType")
        .HasValue<Book>(1) // Book = 1
        .HasValue<SoftwareLicense>(2); // SoftwareLicense = 2
}

4. Interview Mastery

Q: "Because TPH places all properties for all derived classes into a single giant SQL table, doesn't it violate Database Normalization and resulting in massive amounts of NULL data spaces?"

Architect Answer: "Yes, it creates a sparsely populated table. In the table above, `DownloadUrl` is always `NULL` for Books. This seems like bad database design, but SQL Server is incredibly efficient at storing `NULL` values (consuming almost zero physical bytes). The immense advantage of TPH is read performance. If you want to query all Products, TPH executes a single `SELECT * FROM Products`. If you used the alternative 'Table-per-Type' (TPT) approach where each subclass gets its own physical table, EF Core would have to execute a massive, computationally expensive `OUTER JOIN` across all inherited tables just to load a simple catalog. TPH trades perfect normalization for extreme query speed."

Entity Framework Core Mastery
1. Foundations & Architecture
Introduction to Object Relational Mapping (ORM) Entity Framework Core Architecture & Providers Setup and DbContext Integration Code-First vs Database-First Approaches Reverse Engineering Existing Databases (Scaffolding)
2. Code-First Modeling
Entity Conventions & Data Annotations The Fluent API Deep Dive (OnModelCreating) Primary Keys, Composite Keys, & Guids Required Properties & Database Defaults Value Conversions (Enums & Strongly Typed IDs)
3. Relational Architecture
One-to-Many Relationships & Foreign Keys One-to-One Relationships (Dependent Entities) Many-to-Many Relationships & Navigation Properties Owned Entity Types (Value Objects) Table-per-Hierarchy (TPH) Inheritance
4. Data Querying & LINQ
Basic LINQ Queries & IQueryable Execution Tracking vs No-Tracking Queries (Performance) Eager Loading vs Explicit Loading (Include) Lazy Loading Pitfalls & Proxies Client vs Server Evaluation Parsing
5. Manipulating Data (CUD)
Adding, Updating, and Removing Entities The ChangeTracker and Entity States Disconnected Entities in Web APIs Batch Updates and Deletes (.NET 7+)
6. Advanced Performance & Scale
Concurrency Tokens and Optimistic Locking Raw SQL Queries and Views (FromSqlRaw) Compiled Queries for High Throughput Interceptors (Logging & Auditing Data Changes) DbContext Pooling Mechanisms Managing Complex EF Core Migrations (CI/CD)