dotnet/efcore · error · InvalidOperationException

The mapping strategy '{mappingStrategy}' specified on '{enti

Error message

The mapping strategy '{mappingStrategy}' specified on '{entityType}' is not supported for entity types with a discriminator.

What it means

A mapping strategy other than TPH (i.e. TPT or TPC) was configured on a hierarchy whose root has a discriminator property (HasDiscriminator/FindDiscriminatorProperty). Discriminator columns only make sense when all types share one table (TPH), so EF aborts. Thrown from ValidateInheritanceMapping when FindDiscriminatorProperty() != null and mappingStrategy != TPH.

Source

Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:2103

        if (entityType.BaseType != null)
        {
            if (mappingStrategy != null
                && mappingStrategy != (string?)entityType.BaseType[RelationalAnnotationNames.MappingStrategy])
            {
                throw new InvalidOperationException(
                    RelationalStrings.DerivedStrategy(entityType.DisplayName(), mappingStrategy));
            }

            return;
        }

        // Hierarchy mapping strategy must be the same across all types of mappings (only for root types)
        if (entityType.FindDiscriminatorProperty() != null)
        {
            if (mappingStrategy is not null
                and not RelationalAnnotationNames.TphMappingStrategy)
            {
                throw new InvalidOperationException(
                    RelationalStrings.NonTphMappingStrategy(mappingStrategy, entityType.DisplayName()));
            }

            ValidateTphMapping(entityType, StoreObjectType.Table);
            ValidateTphMapping(entityType, StoreObjectType.View);
            ValidateTphMapping(entityType, StoreObjectType.Function);
            ValidateTphMapping(entityType, StoreObjectType.InsertStoredProcedure);
            ValidateTphMapping(entityType, StoreObjectType.DeleteStoredProcedure);
            ValidateTphMapping(entityType, StoreObjectType.UpdateStoredProcedure);

            ValidateDiscriminatorValues(entityType);
        }
        else
        {
            if (mappingStrategy != RelationalAnnotationNames.TpcMappingStrategy
                && entityType.FindPrimaryKey() == null
                && entityType.GetDirectlyDerivedTypes().Any())
            {

View on GitHub (pinned to dbf9771522)

Solutions

  1. Remove HasDiscriminator / the discriminator property configuration when using TPT or TPC.
  2. Switch the strategy back to TPH if a discriminator column is actually desired.
  3. Audit OnModelCreating for any discriminator-related calls when the strategy is non-TPH.

Example fix

// before
modelBuilder.Entity<Person>()
    .HasDiscriminator(p => p.Type).IsComplete(true)
    .UseTptMappingStrategy();
// after (TPC/TPT has no discriminator)
modelBuilder.Entity<Person>().UseTptMappingStrategy();
// remove the discriminator property or stop configuring it
Defensive patterns

Strategy: validation

Validate before calling

using (var ctx = new MyContext()) { ctx.Model.ToDebugString(); }
// Assert no non-TPH strategy coexists with a discriminator property.
foreach (var et in ctx.Model.GetEntityTypes().Where(e => e.BaseType == null))
{
    var s = (string?)et[Microsoft.EntityFrameworkCore.Metadata.RelationalAnnotationNames.MappingStrategy];
    if (et.FindDiscriminatorProperty() != null && s is not null and not "TPH")
        Debug.Fail($"{et.Name} has a discriminator but uses '{s}', not TPH.");
}

Try / catch

try { using var ctx = new MyContext(); _ = ctx.Model; }
catch (InvalidOperationException ex) when (ex.Message.Contains("not supported for entity types with a discriminator"))
{ log.Error("Discriminator + non-TPH strategy; remove one: {Msg}", ex.Message); throw; }

Prevention

When it happens

Trigger: Calling both HasDiscriminator().IsComplete(true) and UseTptMappingStrategy()/UseTpcMappingStrategy() on the same hierarchy; migrating a hierarchy from TPH to TPT/TPC but leaving an explicit HasDiscriminator on the root.

Common situations: Porting a TPH model to TPT and forgetting to remove the discriminator configuration; applying a discriminator out of habit on a hierarchy that was switched to TPC; mixing attributes that imply a discriminator with a non-TPH strategy.

Related errors


AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06). Data as JSON: /api/errors/fd16d1693f574d94. Report an issue: GitHub.