dotnet/efcore · error · InvalidOperationException

Cannot translate the '{comparisonOperator}' on an expression

Error message

Cannot translate the '{comparisonOperator}' on an expression of entity type '{entityType}' because it is a keyless entity. Consider using entity properties instead. For more information on keyless entity types, see https://go.microsoft.com/fwlink/?linkid=2141943.

What it means

Thrown by TryRewriteContainsEntity when a Queryable.Contains call (or entity equality) targets a keyless entity type. Keyless entities have no primary key, so EF cannot rewrite an entity-based Contains/equality into a key comparison for Cosmos SQL. Contains on keyless entities is not translatable.

Source

Thrown at src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.StructuralEquality.cs:37

    private static readonly MethodInfo ParameterListValueExtractorMethod =
        typeof(CosmosSqlTranslatingExpressionVisitor).GetTypeInfo().GetDeclaredMethod(nameof(ParameterListValueExtractor))!;

    private bool TryRewriteContainsEntity(Expression source, Expression item, [NotNullWhen(true)] out Expression? result)
    {
        result = null;

        if (item is not StructuralTypeReferenceExpression { StructuralType: IEntityType entityType })
        {
            return false;
        }

        var primaryKeyProperties = entityType.FindPrimaryKey()?.Properties;

        switch (primaryKeyProperties)
        {
            case null:
                throw new InvalidOperationException(
                    CoreStrings.EntityEqualityOnKeylessEntityNotSupported(
                        nameof(Queryable.Contains), entityType.DisplayName()));

            case { Count: > 1 }:
                throw new InvalidOperationException(
                    CoreStrings.EntityEqualityOnCompositeKeyEntitySubqueryNotSupported(
                        nameof(Queryable.Contains), entityType.DisplayName()));
        }

        var property = primaryKeyProperties[0];
        Expression rewrittenSource;
        switch (source)
        {
            case SqlConstantExpression sqlConstantExpression:
                var values = (IEnumerable)sqlConstantExpression.Value!;
                var propertyValueList =
                    (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(property.ClrType.MakeNullable()))!;
                var propertyGetter = property.GetGetter();

View on GitHub (pinned to dbf9771522)

Solutions

  1. Compare on a concrete property of the keyless entity instead of the entity instance: ids.Contains(v.SomeId).
  2. If the entity should be identifiable, define a key on it (remove HasNoKey) so entity equality can translate.
  3. Materialize to a set of scalar keys client-side and use Contains on those scalars.

Example fix

// before
var view = context.Views.First();
var exists = context.Views.Contains(view);
// after
var viewId = context.Views.Select(v => v.Code).First();
var exists = context.Views.Any(v => v.Code == viewId);
Defensive patterns

Strategy: validation

Validate before calling

// Compare on scalar keys, not on keyless entity references
var codes = views.Select(v => v.Code).ToArray();
var exists = context.Views.Any(v => codes.Contains(v.Code));

Type guard

static bool IsKeyless(IEntityType et) => et.FindPrimaryKey() is null;

Prevention

When it happens

Trigger: Calling .Contains(entity) or comparing entity instances where the entity type is configured HasNoKey(). For example: context.Views.Contains(view) where View is a keyless query root.

Common situations: Using keyless entity types (database views, raw SQL results, read-only projections) in Contains or entity-equality comparisons. Migrating a relational Contains pattern to Cosmos with a keyless type.

Related errors


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