dotnet/efcore · error · InvalidOperationException

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

Error message

The mapping strategy '{mappingStrategy}' specified on '{entityType}' is not supported.

What it means

ValidateMappingStrategy inspects the MappingStrategy annotation placed on a root entity type and only accepts the three known values: TPH, TPC, or TPT (constants in RelationalAnnotationNames). Any other string (including typos, casing mistakes, or a value from a newer/older version) is rejected with an InvalidOperationException, because EF has no code path to honor it.

Source

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

            }
        }
    }

    /// <summary>
    ///     Validates that the given mapping strategy is supported
    /// </summary>
    /// <param name="entityType">The entity type.</param>
    /// <param name="mappingStrategy">The mapping strategy.</param>
    protected virtual void ValidateMappingStrategy(IEntityType entityType, string? mappingStrategy)
    {
        switch (mappingStrategy)
        {
            case RelationalAnnotationNames.TphMappingStrategy:
            case RelationalAnnotationNames.TpcMappingStrategy:
            case RelationalAnnotationNames.TptMappingStrategy:
                break;
            default:
                throw new InvalidOperationException(
                    RelationalStrings.InvalidMappingStrategy(
                        mappingStrategy, entityType.DisplayName()));
        }
    }

    private static void ValidateNonTphMapping(IEntityType rootEntityType, StoreObjectType storeObjectType)
    {
        var isTpc = rootEntityType.GetMappingStrategy() == RelationalAnnotationNames.TpcMappingStrategy;
        var derivedTypes = new Dictionary<StoreObjectIdentifier, IEntityType>();
        foreach (var entityType in rootEntityType.GetDerivedTypesInclusive())
        {
            var storeObject = StoreObjectIdentifier.Create(entityType, storeObjectType);
            if (storeObject == null)
            {
                var unmappedOwnedType = entityType.GetReferencingForeignKeys()
                    .Where(fk => fk.IsOwnership)
                    .Select(fk => fk.DeclaringEntityType)
                    .FirstOrDefault(owned => StoreObjectIdentifier.Create(owned, storeObjectType) == null

View on GitHub (pinned to dbf9771522)

Solutions

  1. Use the fluent API instead of raw annotations: modelBuilder.Entity<Base>().UseTpcMappingStrategy() / UseTptMappingStrategy() / UseTphMappingStrategy().
  2. If setting the annotation by hand, use the RelationalAnnotationNames.TpcMappingStrategy / TptMappingStrategy / TphMappingStrategy constant rather than a string literal.
  3. Verify the EF Core version across all projects is consistent (dotnet list package --include-transitive) so the strategy constant matches what the validator expects.

Example fix

// before
modelBuilder.Entity<Base>().Metadata["Relational:MappingStrategy"] = "TPCC"; // typo

// after
modelBuilder.Entity<Base>().UseTpcMappingStrategy();
Defensive patterns

Strategy: validation

Validate before calling

using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal; // RelationalAnnotationNames is public via the RelationalExtensions

bool StrategyIsValid(IModel model)
{
    var valid = new[] { "TPH", "TPC", "TPT" };
    foreach (var et in model.GetEntityTypes())
    {
        var s = et.GetMappingStrategy();
        if (s is not null && !valid.Contains(s)) return false;
    }
    return true;
}

Try / catch

try { _ = context.Model; }
catch (InvalidOperationException ex) when (ex.Message.Contains("mapping strategy", StringComparison.Ordinal) && ex.Message.Contains("not supported", StringComparison.Ordinal))
{
    throw new InvalidOperationException("Unknown mapping strategy. Use UseTphMappingStrategy()/UseTptMappingStrategy()/UseTpcMappingStrategy().", ex);
}

Prevention

When it happens

Trigger: Produced when entityType[RelationalAnnotationNames.MappingStrategy] is a non-null string other than "TPH", "TPC", or "TPT". Happens if you call .UseTpcMappingStrategy() on a custom fork, hand-set the annotation via .Metadata.FindAnnotation(...).Value = ..., pass a wrong constant, or build the model with code targeting a different EF Core version where a different strategy name was used.

Common situations: Mistyping the strategy name when setting the annotation directly; copy-pasting TPC/TPT code from a blog that uses a deprecated API; upgrading EF Core where strategy constants were renamed; provider plugins that inject a strategy EF does not recognize.

Related errors


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