Repository navigation
EF-359: Fix Count/LongCount over embedded collections in projections - #339
Merged
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes server-side translation of Count and LongCount projections over embedded collections.
Changes:
- Binds collection counts directly for LINQ v3 translation.
- Adds null guards for unfiltered counts.
- Adds functional coverage for filtered, arithmetic, tracking, and null cases.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
MongoProjectionBindingExpressionVisitor.cs |
Binds embedded collection count projections. |
MongoEFToLinqTranslatingExpressionVisitor.cs |
Rewrites unfiltered counts with null handling. |
OwnedEntityTests.cs |
Adds embedded collection count regression tests. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
ajcvickers
force-pushed
the
EF-359
branch
3 times, most recently
from
August 24, 2026 10:14
a2f66ea to
17a5f25
Compare
ajcvickers
added a commit
to ajcvickers/mongo-efcore-provider
that referenced
this pull request
Aug 24, 2026
…-358, EF-376, EF-379, EF-380 and merged upstream PRs mongodb#339, mongodb#350, mongodb#353, mongodb#355, mongodb#357, mongodb#360, mongodb#366, mongodb#367, mongodb#368
ajcvickers
added a commit
to ajcvickers/mongo-efcore-provider
that referenced
this pull request
Sep 30, 2026
…-358, EF-376, EF-379, EF-380 and merged upstream PRs mongodb#339, mongodb#350, mongodb#353, mongodb#355, mongodb#357, mongodb#360, mongodb#366, mongodb#367, mongodb#368
Collaborator
|
@copilot resolve the merge conflicts in this pull request |
damieng
requested changes
Oct 5, 2026
Collaborator
There was a problem hiding this comment.
- Interface-typed owned collections still throw.
Activator.CreateInstanceinMongoEFToLinqTranslatingExpressionVisitor.cscan't buildIList<T>,ICollection<T>,IEnumerable<T>orT[]. A repro threwMissingMethodExceptionon EF10 and EF8. The suggested fix isArray.CreateInstance(elementType, 0)for those types, plus anIList<T>test. - Entity plus Count still fails.
Select(b => new { b, N = b.Posts.Count })throwsThe property 'Blog.N' could not be found, because the mixed-projection visitor doesn't recognise the new Count leaf. - Nested owned Count still fails (nit).
b.Posts.Select(p => p.Tags.Count())throws the "owned entity without a corresponding owner" error.
All three threw before the PR too, so none is a regression but we probably want this to be comprehensive.
Collaborator
Author
|
@damieng Comment 3 is complicated to fix and not a regression. If it's really more than just a nit, then we should file an issue for it. |
Collaborator
Author
|
@damieng Looks like I still need a re-review of this. |
damieng
approved these changes
Oct 19, 2026
- Build the empty fallback collection for interface-typed owned collections (IList<T>, ICollection<T>, IEnumerable<T>) instead of Activator.CreateInstance. - Bind an unfiltered embedded Count/LongCount alongside a whole entity in the mixed projection path by counting the stored array client-side. - Add tests for both. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Supersedes #337
b.Posts.Count(p => p.Rank > 0)andb.Posts.Count()inside a Select projection over an owned (embedded) collection threw InvalidOperationException at translation time in every MongoQueryMode, because MongoProjectionBindingExpressionVisitor had no case for the lowered Queryable.Count(Queryable.AsQueryable(EF.Property(...))) shape and fell into the generic fallback, which tried to visit the predicate lambda's own parameter as an unbound reference.Bind Count/LongCount (with or without a predicate) to the original method-call subtree instead of the materializing shaper, so it stays push-down-able to the driver's own LINQ v3 translation rather than materializing owned entities (which EF Core's tracking-materializer rejects without an owner in the result).
That push-down path also has a null-safety gap for the bare/unfiltered form: the driver renders it as a server-side $size, which throws on a missing/null stored array (unlike the predicated form, which renders as a null-tolerant $map/$sum). Add a narrowly-scoped rewrite in
MongoEFToLinqTranslatingExpressionVisitor that null-guards genuinely embedded navigations with $cond, without touching other AsQueryable(...) shapes (e.g. IGrouping sources in GroupBy/Union pipelines).
This also fixes and subsumes EF-357 (bare/arithmetic-wrapped Count over an embedded collection), including a tracking-query case EF-357's own fix did not handle (its client-side materialization approach hits the same owned-entity-without-owner rejection under a tracking query).