dotnet/efcore · error · InvalidOperationException

Using '{methodName}' on DbSet of '{entityType}' is not suppo

Error message

Using '{methodName}' on DbSet of '{entityType}' is not supported since '{entityType}' is part of hierarchy and does not contain a discriminator property.

What it means

GenerateFromSqlQueryRoot (RelationalQueryableExtensions.cs:192), used by FromSql/FromSqlRaw/FromSqlInterpolated, throws when the target entity type is part of an inheritance hierarchy (has a base type or derived types) but has no discriminator property. FromSql over DbSet needs a single concrete row-to-type mapping; without a discriminator EF cannot decide which hierarchy member each row represents, so it only supports TPH roots with a discriminator.

Source

Thrown at src/EFCore.Relational/Extensions/RelationalQueryableExtensions.cs:192

        return queryableSource.Provider.CreateQuery<TEntity>(
            GenerateFromSqlQueryRoot(
                queryableSource,
                sql.Format,
                sql.GetArguments()));
    }

    private static FromSqlQueryRootExpression GenerateFromSqlQueryRoot(
        IQueryable source,
        string sql,
        object?[] arguments,
        [CallerMemberName] string memberName = null!)
    {
        var entityQueryRootExpression = (EntityQueryRootExpression)source.Expression;

        var entityType = entityQueryRootExpression.EntityType;
        return (entityType.BaseType != null || entityType.GetDirectlyDerivedTypes().Any())
            && entityType.FindDiscriminatorProperty() == null
                ? throw new InvalidOperationException(
                    RelationalStrings.MethodOnNonTphRootNotSupported(memberName, entityType.DisplayName()))
                : new FromSqlQueryRootExpression(
                    entityQueryRootExpression.QueryProvider!,
                    entityType,
                    sql,
                    Expression.Constant(arguments));
    }

    #endregion

    #region SplitQuery

    /// <summary>
    ///     Returns a new query which is configured to load the collections in the query results in a single database query.
    /// </summary>
    /// <remarks>
    ///     <para>
    ///         This behavior generally guarantees result consistency in the face of concurrent updates

View on GitHub (pinned to dbf9771522)

Solutions

  1. Call FromSql on the hierarchy root DbSet and let EF route rows by discriminator (requires TPH with a configured discriminator).
  2. If using TPT/TPC, switch to a plain SQL projection (e.g. context.Set<DerivedEntity>().FromSqlRaw on a TVF/view is not supported either) - instead execute raw SQL via ADO.NET or use a keyless entity/SQL query mapping.
  3. Ensure the discriminator is configured: modelBuilder.Entity<Base>().HasDiscriminator(b => b.Type) and that the entity is the TPH root.
  4. If you must target a derived type only, map a separate keyless entity or a defining query backed by raw SQL.

Example fix

// before (TPT/TPC, derived type)
var managers = context.Set<Manager>().FromSqlRaw("SELECT * FROM Managers").ToList(); // throws

// after - query the root in a TPH hierarchy with discriminator
var managers = context.Employees
    .FromSqlRaw("SELECT * FROM Employees WHERE Discriminator = 'Manager'")
    .OfType<Manager>().ToList();
Defensive patterns

Strategy: validation

Validate before calling

IEntityType entityType = context.Model.FindEntityType(typeof(TEntity))!;
bool isHierarchyRoot = entityType.BaseType == null;
bool hasDiscriminator = entityType.FindDiscriminatorProperty() != null;
bool inHierarchy = entityType.BaseType != null || entityType.GetDerivedTypes().Any();
if (inHierarchy && !hasDiscriminator)
{
    // FromSql on this DbSet will throw; query the root or avoid FromSql.
}

Type guard

static bool SupportsFromSql<T>(IModel model) where T : class
{
    var et = model.FindEntityType(typeof(T))!;
    var inHierarchy = et.BaseType != null || et.GetDerivedTypes().Any();
    return !inHierarchy || et.FindDiscriminatorProperty() != null;
}

Prevention

When it happens

Trigger: Calling context.Set<DerivedEntity>().FromSqlRaw(...) or FromSqlInterpolated on a DbSet whose entity is in a TPT/TPC hierarchy, or a TPH hierarchy where the discriminator was removed/misconfigured. Also triggers when calling FromSql on a derived type rather than the hierarchy root.

Common situations: TPT or TPC hierarchies (no shared discriminator); mapped a discriminator but later removed it; calling FromSql on a derived entity instead of the base; hierarchy recently refactored from TPH to TPT.

Related errors


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