EF Core TPC Inheritance — Complete Guide
In this tutorial, you'll learn about EF Core TPC Inheritance. We cover key concepts, practical examples, and best practices.
You have a base Payment class with subclasses CreditCardPayment and PayPalPayment. You need to store them in separate tables — each table has all columns including the base class properties. TPC (Table-Per-Concrete-Type) mapping in EF Core creates one table per concrete class with all columns.
Wrong
public 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; }
}
Default TPH: All types in one Payments table with a discriminator column. CardNumber and Email columns are nullable.
Right (TPC)
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Payment>().UseTpcMappingStrategy()
.ToTable("Payments");
modelBuilder.Entity<CreditCardPayment>()
.ToTable("CreditCardPayments");
modelBuilder.Entity<PayPalPayment>()
.ToTable("PayPalPayments");
}
Output: Three tables:
Payments(justId,Amount) — can be abstractCreditCardPayments(Id,Amount,CardNumber)PayPalPayments(Id,Amount,Email)
Each table is complete — no sharing, no joins for concrete type queries.
Prevention
- Use TPC when concrete types have different columns and you rarely query the base type.
- Use TPC for better query performance on concrete types (no discriminator column, no joins).
- Use TPC with
abstractbase entity when you never query the base type directly. - Use TPC when you need non-nullable columns per type (TPH would make them nullable).
- Use TPH when you frequently query the base type across all subtypes.
- Use TPT when you want normalized tables per type (base columns in one table, subtype columns in another).
Common Mistakes with core tpc inheritance
- Mixing let bindings with <- bindings in do notation, producing type errors
- Overlapping type class instances that cause GHC to reject the program with ambiguous dispatch errors
- Non-exhaustive pattern matches that compile with warnings then crash at runtime
These mistakes appear frequently in real-world EF code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.
Practice Exercise
Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.
This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.
FAQ
TPC is used in DodaTech's payment processing for separate payment method tables. For more EF Core, visit DodaTech.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro