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
- Remove HasDiscriminator / the discriminator property configuration when using TPT or TPC.
- Switch the strategy back to TPH if a discriminator column is actually desired.
- 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 switching to TPT/TPC, remove all HasDiscriminator configuration from the root.
- Prefer the UseXxxMappingStrategy() API over manually mixing discriminator configuration.
- Cover the discriminator-vs-strategy invariant in a startup model-build test.
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
- The specified discriminator value '{value}' for '{entityType
- The derived entity type '{entityType}' was configured with t
- The short name for '{entityType1}' is '{discriminatorValue}'
- The mapping strategy '{mappingStrategy}' used for '{entityTy
- Both '{entityType}' and '{otherEntityType}' are mapped to th
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/fd16d1693f574d94.
Report an issue: GitHub.