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 throws InvalidOperationException when the replacement IEntityType differs from the query root's entity type in either Name or CLR type. The query root is bound to a specific entity type (its SQL and argument are tied to it), so swapping to a different entity would be invalid; EF requires an exact name+CLR match.

Source

Thrown at src/EFCore.Relational/Query/Internal/FromSqlQueryRootExpression.cs:81

    /// <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. Pass an IEntityType with the same Name and the same ClrType as the original query root's EntityType.
  2. If you need a different entity, construct a new FromSqlQueryRootExpression for that entity rather than updating an existing one.
  3. Avoid mutating query roots in custom visitors; rebuild the tree from the correct entity type.

Example fix

// before
var newRoot = fromSqlRoot.UpdateEntityType(otherEntityType); // name/CLR differs -> throws

// after - use a matching entity type, or build a new root
var matching = model.FindEntityType(typeof(Order))!; // same Name + ClrType
var newRoot = fromSqlRoot.UpdateEntityType(matching);
// or:
var fresh = new FromSqlQueryRootExpression(queryProvider, otherEntityType, sql, arg);
Defensive patterns

Strategy: validation

Validate before calling

static IEntityType ValidateSameEntity(IEntityType original, IEntityType replacement)
{
    if (replacement.Name != original.Name || replacement.ClrType != original.ClrType)
        throw new InvalidOperationException($"Replacement entity {replacement.DisplayName()} differs from {original.DisplayName()}.");
    return replacement;
}

Type guard

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

Try / catch

try { return root.UpdateEntityType(replacement); }
catch (InvalidOperationException ex) when (ex.Message.Contains("does not have same name and CLR type"))
{ /* construct a fresh query root for the new entity instead */ throw; }

Prevention

When it happens

Trigger: Calling UpdateEntityType with an IEntityType whose Name (model-qualified name) or ClrType differs from the original; a query-translation extension attempting to retarget a FromSql query root to a different entity; model remapping that changes the entity type mid-translation.

Common situations: Custom query translators/visitors that try to swap entity types; TPH/TPT inheritance remapping gone wrong; using a replacement entity type built for a different CLR type; EF extension libraries mismatching entity types during tree rewriting.

Related errors


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