dotnet/efcore · error · InvalidOperationException
Cannot translate ' ' on a subquery expression of entity…
Error message
Cannot translate '{comparisonOperator}' on a subquery expression of entity type '{entityType}' because it has a composite primary key. See https://go.microsoft.com/fwlink/?linkid=2141942 for information on how to rewrite your query. What it means
For Contains on a subquery of entities, StructuralEquality can only expand to an IN against a single key property. When the primary key has more than one property (composite key) there is no single column to compare, so it throws CoreStrings.EntityEqualityOnCompositeKeyEntitySubqueryNotSupported.
Solutions
- Rewrite as an explicit join or as separate Any-based predicates over each key property.
- Project to a scalar comparable value (a derived single-column key) before Contains.
- Materialize the candidate set client-side and do the equality check in memory if volumes are small.
Example fix
// before
var q = db.Items.Where(i => allowed.Contains(i));
// after
var q = db.Items.Where(i =>
allowed.Any(a => a.TenantId == i.TenantId && a.LocalId == i.LocalId)); Defensive patterns
Strategy: validation
Validate before calling
// rewrite Contains on composite-key entities as Any over all key parts
static IQueryable<T> MatchAny<T>(IQueryable<T> q, IReadOnlyList<T> candidates,
Func<T, Expression<Func<T, bool>>> predicate)
where T : class
{
Expression<Func<T, bool>> body = _ => false;
foreach (var c in candidates) body = CombineOr(body, predicate(c));
return q.Where(body);
} Type guard
static bool HasCompositeKey<T>(DbContext ctx)
=> (ctx.Model.FindEntityType(typeof(T))?.FindPrimaryKey()?.Properties.Count ?? 0) > 1; Prevention
- Replace Contains-on-entity with explicit Any over key properties.
- Add a test that flags Contains on composite-key entity types.
- Document composite-key IN translation limits in team guidance.
When it happens
Trigger: Queryable.Contains(entity) where the entity has a composite primary key and the source is a subquery/constant list, so EF cannot translate to a single-column IN.
Common situations: Join-like filtering using Contains against entities whose key spans multiple properties (e.g. TenantId + LocalId), or migrating a single-key Contains query after adding a second key column.
Related errors
- Cannot translate the
- A FromSqlExpression has an invalid arguments expression type
- Bind property on structural type coming out of scalar…
- Cannot translate ' ' on a subquery expression of entity…
- Complex projections in subqueries are currently unsupported.
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/f7ba9f9ec4274544.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.StructuralEquality.cs:42
{
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();
foreach (var value in values)
{
propertyValueList.Add(propertyGetter.GetClrValue(value));
}
View on GitHub (pinned to 3a2006ef56)