dotnet/efcore · error · InvalidOperationException

The entity type ' ' is mapped to a SQL query, but is…

Error message

The entity type '{entityType}' is mapped to a SQL query, but is derived from '{baseEntityType}'. Derived entity types cannot be mapped to a different SQL query than the base entity type.

What it means

ValidateSqlQuery throws InvalidMappedSqlQueryDerivedType when an entity type mapped to a SQL query (via ToSqlQuery/ToSqlQueryRaw) has a base type and either lacks a discriminator or its SQL query differs from its base's. Relational mapping requires that a derived entity in a hierarchy share the same defining SQL query as its base — only TPH-over-SQL-query is supported.

Solutions

  1. Define the SQL query only on the hierarchy root entity type and let derived types inherit it.
  2. If using TPH, ensure a discriminator is configured and only the root has ToSqlQuery.
  3. For per-type querying, use separate non-hierarchical entity types or FromSqlRaw on the root with discriminator filtering.

Example fix

// before — derived type has its own SQL query
modelBuilder.Entity<Base>().ToSqlQuery("SELECT * FROM base_view");
modelBuilder.Entity<Derived>().ToSqlQuery("SELECT * FROM derived_view"); // throws

// after — root owns the SQL query; derived types inherit
modelBuilder.Entity<Base>().ToSqlQuery("SELECT * FROM base_view");
modelBuilder.Entity<Derived>().HasBase<Base>(); // no ToSqlQuery here
Defensive patterns

Strategy: validation

Validate before calling

if (entityType.BaseType != null && entityType.GetSqlQuery() is not null
    && (entityType.FindDiscriminatorProperty() == null
        || entityType.GetSqlQuery() != entityType.BaseType.GetSqlQuery()))
    throw new InvalidOperationException("Derived entity cannot have a different SQL query than its base.");

Type guard

static bool CanMapToSqlQuery(IEntityType e)
    => e.BaseType == null
       || (e.FindDiscriminatorProperty() is not null
           && e.GetSqlQuery() == e.BaseType?.GetSqlQuery());

Prevention

When it happens

Trigger: Configuring ToSqlQuery("SELECT ...") on a derived entity type; or giving a derived entity a different SQL query string than its base while the hierarchy uses no discriminator. Either condition triggers the throw.

Common situations: Trying to use SQL-query mapping (e.g. database views or TVFs) per derived type in a TPT hierarchy; refactoring inheritance and forgetting to remove a ToSqlQuery on the derived type; scaffolding views in an inheritance hierarchy.

Related errors


AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11). Data as JSON: /api/errors/9aff8508d0c9c6c9. Report an issue: GitHub.

Appendix: source

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

    ///     Validates the SQL query mapping for an entity type.
    /// </summary>
    /// <param name="entityType">The entity type to validate.</param>
    /// <param name="logger">The logger to use.</param>
    protected virtual void ValidateSqlQuery(
        IEntityType entityType,
        IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger)
    {
        var sqlQuery = entityType.GetSqlQuery();
        if (sqlQuery == null)
        {
            return;
        }

        if (entityType.BaseType != null
            && (entityType.FindDiscriminatorProperty() == null
                || sqlQuery != entityType.BaseType.GetSqlQuery()))
        {
            throw new InvalidOperationException(
                RelationalStrings.InvalidMappedSqlQueryDerivedType(
                    entityType.DisplayName(), entityType.BaseType.DisplayName()));
        }
    }

    /// <summary>
    ///     Validates a single sequence.
    /// </summary>
    /// <param name="sequence">The sequence to validate.</param>
    /// <param name="logger">The logger to use.</param>
    protected virtual void ValidateSequence(
        ISequence sequence,
        IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger)
    {
    }

    /// <summary>
    ///     Validates a single database function.

View on GitHub (pinned to 3a2006ef56)