Skip to content

EF-357: Fix ArgumentException on bare embedded-collection Count projections - #337

Closed
ajcvickers wants to merge 1 commit into
mongodb:mainfrom
ajcvickers:EF-357
Closed

ajcvickers wants to merge 1 commit into
mongodb:mainfrom
ajcvickers:EF-357

Conversation

@ajcvickers

Copy link
Copy Markdown
Collaborator

db.Set().Select(e => e.OwnedCollection.Count) threw ArgumentException in every case (bare and arithmetic-wrapped alike), because EF Core lowers a collection-navigation Count to Queryable.Count(Queryable.AsQueryable(source)) even for an in-document embedded List, and
MongoProjectionBindingExpressionVisitor had no case for that shape - it fell into the generic fallback, which tried to rebuild the Queryable.Count call with the already-materialized List, which isn't an IQueryable.

Add TryBindEmbeddedCollectionNavigationCount to recognize the shape and rewrite it as a null-safe Enumerable.Count/LongCount over the navigation's CollectionShaperExpression (null-safe because a missing/explicitly-null stored array materializes to null rather than an empty collection).

…ctions

db.Set<T>().Select(e => e.OwnedCollection.Count) threw ArgumentException in
every case (bare and arithmetic-wrapped alike), because EF Core lowers a
collection-navigation Count to Queryable.Count(Queryable.AsQueryable(source))
even for an in-document embedded List<T>, and
MongoProjectionBindingExpressionVisitor had no case for that shape - it fell
into the generic fallback, which tried to rebuild the Queryable.Count call
with the already-materialized List<T>, which isn't an IQueryable<T>.

Add TryBindEmbeddedCollectionNavigationCount to recognize the shape and
rewrite it as a null-safe Enumerable.Count/LongCount over the navigation's
CollectionShaperExpression (null-safe because a missing/explicitly-null
stored array materializes to null rather than an empty collection).
@ajcvickers
ajcvickers requested a review from damieng August 12, 2026 15:46
@ajcvickers
ajcvickers requested a review from a team as a code owner August 12, 2026 15:46
Copilot AI lite review requested due to automatic review settings August 12, 2026 15:46

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a query translation/binding gap in the MongoDB EF Core provider where projecting OwnedCollection.Count (or LongCount) over an embedded owned collection could throw ArgumentException due to EF Core lowering the expression into a Queryable.Count(Queryable.AsQueryable(source)) shape that doesn’t match the provider’s fallback binding logic.

Changes:

  • Add a dedicated binding path in MongoProjectionBindingExpressionVisitor to detect embedded-navigation Count/LongCount lowered as Queryable.*(Queryable.AsQueryable(...)) and rewrite to a null-safe Enumerable.Count/LongCount over the CollectionShaperExpression.
  • Add functional tests to cover bare Count/LongCount projections and arithmetic-wrapped Count over an owned embedded collection, including null/empty cases.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
tests/MongoDB.EntityFrameworkCore.FunctionalTests/Query/OwnedEntityTests.cs Adds regression tests for Count/LongCount projections over embedded owned collections (bare and wrapped).
src/MongoDB.EntityFrameworkCore/Query/Visitors/MongoProjectionBindingExpressionVisitor.cs Adds embedded-collection Count/LongCount binding logic and null-safe helpers to avoid Queryable.Count rebuild failures.
Suppressed comments (1)

src/MongoDB.EntityFrameworkCore/Query/Visitors/MongoProjectionBindingExpressionVisitor.cs:763

  • NullSafeLongCount is intended to tolerate a null embedded collection (mirroring NullSafeCount), but its parameter is declared non-nullable IEnumerable even though the implementation treats it as nullable. Make the parameter nullable so the signature matches behavior and intent under enable.
    private static long NullSafeLongCount<T>(IEnumerable<T> source)
        => source?.LongCount() ?? 0;

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@ajcvickers

Copy link
Copy Markdown
Collaborator Author

Superseded by #339

@ajcvickers ajcvickers closed this Aug 13, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants