{"record":{"id":"f7ba9f9ec4274544","repo":"dotnet/efcore","slug":"cannot-translate-comparisonoperator-on-a-subqu","errorCode":null,"errorMessage":"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.","messagePattern":"Cannot translate '(.+?)' on a subquery expression of entity type '(.+?)' because it has a composite primary key\\. See https://go\\.microsoft\\.com/fwlink/\\?linkid=2141942 for information on how to rewrite your query\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.StructuralEquality.cs","lineNumber":42,"sourceCode":"    {\n        result = null;\n\n        if (item is not StructuralTypeReferenceExpression { StructuralType: IEntityType entityType })\n        {\n            return false;\n        }\n\n        var primaryKeyProperties = entityType.FindPrimaryKey()?.Properties;\n\n        switch (primaryKeyProperties)\n        {\n            case null:\n                throw new InvalidOperationException(\n                    CoreStrings.EntityEqualityOnKeylessEntityNotSupported(\n                        nameof(Queryable.Contains), entityType.DisplayName()));\n\n            case { Count: > 1 }:\n                throw new InvalidOperationException(\n                    CoreStrings.EntityEqualityOnCompositeKeyEntitySubqueryNotSupported(\n                        nameof(Queryable.Contains), entityType.DisplayName()));\n        }\n\n        var property = primaryKeyProperties[0];\n        Expression rewrittenSource;\n        switch (source)\n        {\n            case SqlConstantExpression sqlConstantExpression:\n                var values = (IEnumerable)sqlConstantExpression.Value!;\n                var propertyValueList =\n                    (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(property.ClrType.MakeNullable()))!;\n                var propertyGetter = property.GetGetter();\n                foreach (var value in values)\n                {\n                    propertyValueList.Add(propertyGetter.GetClrValue(value));\n                }\n","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/dotnet/efcore/blob/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.StructuralEquality.cs#L24-L60","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nvar q = db.Items.Where(i => allowed.Contains(i));\n// after\nvar q = db.Items.Where(i =>\n    allowed.Any(a => a.TenantId == i.TenantId && a.LocalId == i.LocalId));","handlingStrategy":"validation","validationCode":"// rewrite Contains on composite-key entities as Any over all key parts\nstatic IQueryable<T> MatchAny<T>(IQueryable<T> q, IReadOnlyList<T> candidates,\n    Func<T, Expression<Func<T, bool>>> predicate)\n    where T : class\n{\n    Expression<Func<T, bool>> body = _ => false;\n    foreach (var c in candidates) body = CombineOr(body, predicate(c));\n    return q.Where(body);\n}","typeGuard":"static bool HasCompositeKey<T>(DbContext ctx)\n    => (ctx.Model.FindEntityType(typeof(T))?.FindPrimaryKey()?.Properties.Count ?? 0) > 1;","tryCatchPattern":null,"preventionTips":["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."],"tags":["cosmos","entity-equality","composite-key","query-translation"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}