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

  1. Remove the subquery/collection from the projection before calling Distinct, then re-attach it after materialization.
  2. Call AsEnumerable() before Distinct to perform deduplication client-side on the materialized objects.
  3. 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

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


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)