Tuesday, March 17, 2026

EF Core 11.0: Complex Types and JSON Columns on Entity Types with TPT/TPC Inheritance

In this post, let's have a look at a nice improvement in EF Core 11 around complex types, JSON columns, and inheritance mapping.

If you tried to use a complex type as a JSON column on an entity hierarchy that uses TPT (Table-per-Type) or TPC (Table-per-Concrete-Type) in EF Core 10, you would have noticed that it was not working as expected. With EF Core 11, that limitation is now gone.

Let's see how this works.

Consider the following Db Context.

public abstract class Person
{
    public int Id { get; set; }

    public required string Name { get; init; }

    public required Address Address { get; set; }
}

public class Student : Person
{
    public required string School { get; set; }
}

public class Employee : Person
{
    public required string Employer { get; set; }
}

[ComplexType]
public class Address
{
    public required string AddressLine1 { get; set; }

    public required string City { get; set; }

    public required string State { get; set; }
}

public class MyDbContext : DbContext
{
    public DbSet<Student> Students { get; set; }

    public DbSet<Employee> Employees { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        // Note: Database compatibility level 170 (Microsoft SQL Server 2025)
        optionsBuilder
            .UseSqlServer(@"<Connection_String>");
    }

    override protected void OnModelCreating(ModelBuilder modelBuilder)
    {
        // TODO: Configure
    }
}

TPT (Table-per-Type)

EF Core 10

Let's first see TPT with EF Core 10.

override protected void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Person>()
        .UseTptMappingStrategy();
}

This would generate 3 tables: Person, Students and Employees.

EF 10 TPT: Person, Students and Employees
Which is good, working as expected.
 
Now if we try using Complex Types:

override protected void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Person>()
        .UseTptMappingStrategy()
        .ComplexProperty(a => a.Address, b => b.ToJson());
}

This would be an error.

EF Core 11

With EF Core 11.0, above would create: again 3 tables: Person, Students and Employees.

EF 11 TPT: Person, Students and Employees: Identical to EF Core 10.0
EF 11 TPT: Person, Students and Employees with JSON Columns
Note: here the JSON column should be created only in the Parent table.

TPC (Table-per-Concrete-Type)

EF Core 10

Now let's now see TPC with EF Core 10.

override protected void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Person>()
        .UseTpcMappingStrategy();
}

This would generate only 2 tables per concrete types: Students and Employees.

EF 10 TPC: Students and Employees
Note: Here the Address column is missing.

Now if we try using Complex Types:

override protected void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Person>()
        .UseTpcMappingStrategy()
        .ComplexProperty(a => a.Address, b => b.ToJson());
}

This again would be an error.

EF Core 11

With EF Core 11.0, above would create: again 2 tables: Students and Employees.

EF 11 TPC: Students and Employees
EF 11 TPC: Students and Employees with JSON Columns
Here on TPC, everything seems to be working as expected.

Hope this helps.

Read more:

Happy Coding.

Regards,
Jaliya

No comments:

Post a Comment