dotnet/efcore · error · InvalidOperationException
Using 'Distinct' operation on a projection containing a…
Error message
Using 'Distinct' operation on a projection containing a subquery is not supported.
What it means
When the InMemory provider applies Distinct (ApplyDistinct), it walks every accumulated client projection slot. If any slot is itself an InMemoryQueryExpression (i.e. a nested subquery), the provider cannot deduplicate because the subquery result is not a scalar value it can compare at the ValueBuffer level. It throws DistinctOnSubqueryNotSupported from the loop that processes _clientProjections.
Solutions
- Remove the subquery/collection from the projection before calling Distinct, then re-attach it after materialization.
- Call AsEnumerable() before Distinct to perform deduplication client-side on the materialized objects.
- Use GroupBy or SelectMany to flatten the data so Distinct operates on scalar values only.
Example fix
// before — Distinct on a projection containing a subquery
var result = ctx.Blogs
.Select(b => new { b.Title, PostCount = b.Posts.Count() })
.Distinct();
// after — materialize then Distinct client-side
var result = ctx.Blogs
.Select(b => new { b.Title, PostCount = b.Posts.Count() })
.AsEnumerable()
.Distinct(); Defensive patterns
Strategy: validation
Validate before calling
// Validate: do not call Distinct() on a projection that includes a subquery // or collection navigation. Project scalar values only before Distinct. // If the projection must include subqueries, call AsEnumerable() first. var distinctTitles = ctx.Blogs.Select(b => b.Title).Distinct(); // safe — scalar only
Try / catch
try
{
return query.Distinct().ToList();
}
catch (InvalidOperationException ex) when (ex.Message.Contains("Distinct"))
{
// Materialize first, then apply Distinct client-side
return query.AsEnumerable().Distinct().ToList();
} Prevention
- Project only scalar values before calling Distinct.
- Remove collection navigations and subqueries from the Select before Distinct.
- Use AsEnumerable() before Distinct when the projection must include subqueries.
- Consider GroupBy on a key property instead of Distinct on complex projections.
When it happens
Trigger: Calling Distinct() on a query whose projection includes a collection navigation or subquery that has been accumulated as a client projection. The throw occurs during ApplyDistinct when iterating over client projection slots.
Common situations: Projecting a collection navigation (e.g. .Select(b => new { b.Title, b.Posts })) and then calling .Distinct(), or using a correlated subquery inside a Select followed by Distinct. Common when trying to deduplicate parent rows after eagerly loading children.
Related errors
- 'DefaultIfEmpty' cannot be applied after a client-evaluated…
- The LINQ expression ' ' could not be translated. Either…
- The LINQ expression ' ' could not be translated. Additional…
- Unable to translate set operation after client projection…
- A synchronous store management operation was performed and…
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/d239dda6d6e6df8b.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs:515
var selectorExpressions = new List<Expression>();
if (_clientProjections.Count == 0)
{
selectorExpressions.AddRange(_projectionMappingExpressions);
if (selectorExpressions.Count == 0)
{
// No server correlated term in projection so add dummy 1.
selectorExpressions.Add(Constant(1));
}
}
else
{
for (var i = 0; i < _clientProjections.Count; i++)
{
var projection = _clientProjections[i];
if (projection is InMemoryQueryExpression)
{
throw new InvalidOperationException(InMemoryStrings.DistinctOnSubqueryNotSupported);
}
if (projection is EntityProjectionExpression entityProjectionExpression)
{
_clientProjections[i] = TraverseEntityProjection(
selectorExpressions, entityProjectionExpression, makeNullable: false);
}
else
{
selectorExpressions.Add(projection);
_clientProjections[i] = CreateReadValueExpression(
projection.Type, selectorExpressions.Count - 1, InferPropertyFromInner(projection));
}
}
}
var selectorLambda = Lambda(
New(View on GitHub (pinned to 3a2006ef56)