dotnet/efcore · error · InvalidOperationException

The replacement entity type: {entityType} does not have same

Error message

The replacement entity type: {entityType} does not have same name and CLR type as entity type this query root represents.

What it means

FromSqlQueryRootExpression.UpdateEntityType replaces the entity type backing a FromSqlRaw/FromSqlInterpolated query root during query compilation. It requires the replacement type to have both the same Name and the same ClrType as the original; otherwise it throws InvalidOperationException. This guards the identity contract of a raw-SQL query root.

Source

Thrown at src/EFCore.Cosmos/Query/Internal/Expressions/FromSqlQueryRootExpression.cs:83

    /// <summary>
    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
    ///     any release. You should only use it directly in your code with extreme caution and knowing that
    ///     doing so can result in application failures when updating to a new Entity Framework Core release.
    /// </summary>
    public override Expression DetachQueryProvider()
        => new FromSqlQueryRootExpression(EntityType, Sql, Argument);

    /// <summary>
    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
    ///     any release. You should only use it directly in your code with extreme caution and knowing that
    ///     doing so can result in application failures when updating to a new Entity Framework Core release.
    /// </summary>
    public override EntityQueryRootExpression UpdateEntityType(IEntityType entityType)
        => entityType.ClrType != EntityType.ClrType
            || entityType.Name != EntityType.Name
                ? throw new InvalidOperationException(CoreStrings.QueryRootDifferentEntityType(entityType.DisplayName()))
                : new FromSqlQueryRootExpression(entityType, Sql, Argument);

    /// <summary>
    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
    ///     any release. You should only use it directly in your code with extreme caution and knowing that
    ///     doing so can result in application failures when updating to a new Entity Framework Core release.
    /// </summary>
    protected override Expression VisitChildren(ExpressionVisitor visitor)
    {
        var argument = visitor.Visit(Argument);

        return argument != Argument
            ? new FromSqlQueryRootExpression(EntityType, Sql, argument)
            : this;
    }

    /// <summary>

View on GitHub (pinned to dbf9771522)

Solutions

  1. Issue FromSqlRaw against the DbSet of the exact entity type you intend to query and avoid OfType/casts that change entity identity.
  2. If you need a derived view, write the SQL against that entity's container and call FromSqlRaw on its DbSet.
  3. Project into a DTO via Select instead of changing the query root's entity type.

Example fix

// before
var orders = ctx.Set<BaseOrder>()
    .FromSqlRaw("SELECT * FROM c")
    .OfType<SpecialOrder>(); // throws if identity differs

// after
var orders = ctx.Set<SpecialOrder>()
    .FromSqlRaw("SELECT * FROM c WHERE c.Discriminator = 'SpecialOrder'");
Defensive patterns

Strategy: validation

Validate before calling

// Ensure OfType/cast target shares Name + ClrType with the FromSql root.
var root = cosmosModel.FindEntityType(typeof(BaseOrder))!;
var target = cosmosModel.FindEntityType(typeof(T))!;
if (root.Name != target.Name || root.ClrType != target.ClrType)
    throw new InvalidOperationException("OfType target must match FromSql root identity.");

Type guard

static bool IsSameQueryRootIdentity(IEntityType a, IEntityType b)
    => a.Name == b.Name && a.ClrType == b.ClrType;

Try / catch

try { var q = ctx.Set<BaseOrder>().FromSqlRaw(sql).ToList(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("does not have same name and CLR type"))
{ /* reissue FromSqlRaw on the correct DbSet */ }

Prevention

When it happens

Trigger: Combining FromSqlRaw/FromSqlInterpolated with operators (e.g. OfType<T>, casts, or projection rewrites) that cause the pipeline to swap the root's entity type for one whose CLR type or model Name differs.

Common situations: Calling OfType<DerivedType>() on a FromSqlRaw query where DerivedType is not the same identity as the root entity; mixing raw SQL roots with inheritance hierarchies; upgrading EF Core and hitting a changed rewrite path.

Related errors


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