[release/11.0] Lift mixed outer-reference aggregate arguments - #38925
Conversation
- Track, per aggregate invocation, whether the argument references a column of the SELECT the aggregate is evaluated in (local) and whether it references a column from further out (outer), and lift the argument when both are present. The postprocessor only lifted arguments containing a subquery, so these expressions reached the server unmodified and failed with "Multiple columns are specified in an aggregated expression containing an outer reference" - Rename SqlServerAggregateOverSubqueryPostprocessor to SqlServerAggregateArgumentPostprocessor, since a subquery in the argument is no longer the only thing that triggers a lift - Compare against the aggregating SELECT's own table aliases rather than _tableAliasesInScope: that set deliberately excludes those tables, since a lifted subquery reaches them through APPLY rather than CROSS JOIN - Leave an aggregate whose argument is purely an outer reference alone; SQL Server evaluates it in the outer query, which is how aggregates over an outer grouping are meant to translate - Restore the parent visitor state before building the lifted subquery, and capture _isCorrelatedSubquery for the OUTER APPLY/CROSS JOIN choice, so the state saved by an enclosing aggregate is no longer clobbered - Add specification tests for a Sum over an expression with an outer reference and for Sums over members of a single-result subquery, plus SQL Server baselines Fixes #38834 Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
The new relational spec test dereferences a nullable FirstOrDefault() result (d.OrderID) and will fail the build due to warnings-as-errors.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR addresses a SQL Server limitation where aggregate arguments that mix an outer reference with a local column (SQL error 8124) produce invalid SQL, by detecting that pattern during postprocessing and lifting the aggregate argument via OUTER APPLY/CROSS JOIN. It also adds regression coverage for both the direct mixed-reference case and the single-result-subquery projection case.
Changes:
- Extend/rename the SQL Server aggregate argument postprocessor to lift arguments that contain both local and outer references (in addition to the existing “contains subquery” trigger).
- Fix visitor state handling for nested aggregates by restoring parent state before performing the lift while capturing correlation state.
- Add relational spec tests and SQL Server baselines covering mixed outer/local aggregate arguments and the single-result-subquery member projection regression.
File summaries
| File | Description |
|---|---|
| test/EFCore.SqlServer.FunctionalTests/Query/NorthwindAggregateOperatorsQuerySqlServerTest.cs | Adds SQL Server baselines asserting the lifted OUTER APPLY shape for the new regression tests. |
| test/EFCore.Relational.Specification.Tests/Query/NorthwindAggregateOperatorsQueryRelationalTestBase.cs | Adds two new relational spec tests covering mixed outer-reference aggregate arguments (direct and via projected single-result subquery). |
| src/EFCore.SqlServer/Query/Internal/SqlServerQueryTranslationPostprocessor.cs | Switches to the renamed/extended aggregate argument postprocessor. |
| src/EFCore.SqlServer/Query/Internal/SqlServerAggregateArgumentPostprocessor.cs | Implements mixed local/outer reference detection and lifts aggregate arguments to avoid SQL Server error 8124. |
Review details
- Files reviewed: 4/4 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
artl93
left a comment
There was a problem hiding this comment.
regression. user reported. no workaround. approved.
* Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-runtime build 20260803.5 On relative base path root Microsoft.Extensions.HostFactoryResolver.Sources , Microsoft.NETCore.BrowserDebugHost.Transport From Version 8.0.30-servicing.26367.20 -> To Version 8.0.30-servicing.26403.5 * Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-runtime build 20260810.19 On relative base path root Microsoft.Extensions.Caching.Memory , Microsoft.Extensions.Configuration , Microsoft.Extensions.Configuration.Abstractions , Microsoft.Extensions.Configuration.EnvironmentVariables , Microsoft.Extensions.Configuration.Json , Microsoft.Extensions.DependencyInjection , Microsoft.Extensions.DependencyModel , Microsoft.Extensions.Logging , Microsoft.NETCore.App.Ref , Microsoft.NETCore.App.Runtime.win-x64 , System.Formats.Asn1 , System.Text.Encodings.Web , System.Text.Json From Version 9.0.19 -> To Version 9.0.20 Microsoft.Extensions.HostFactoryResolver.Sources , Microsoft.NETCore.BrowserDebugHost.Transport From Version 9.0.19-servicing.26367.24 -> To Version 9.0.20-servicing.26410.19 * Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-runtime build 20260810.18 On relative base path root Microsoft.Extensions.HostFactoryResolver.Sources , Microsoft.NETCore.BrowserDebugHost.Transport From Version 8.0.30-servicing.26367.20 -> To Version 8.0.31-servicing.26410.18 Microsoft.NETCore.App.Ref , Microsoft.NETCore.App.Runtime.win-x64 From Version 8.0.30 -> To Version 8.0.31 * Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-runtime build 20260812.28 On relative base path root Microsoft.Extensions.HostFactoryResolver.Sources , Microsoft.NETCore.BrowserDebugHost.Transport From Version 8.0.30-servicing.26367.20 -> To Version 8.0.31-servicing.26412.28 Microsoft.NETCore.App.Ref , Microsoft.NETCore.App.Runtime.win-x64 From Version 8.0.30 -> To Version 8.0.31 * Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-runtime build 20260813.7 On relative base path root Microsoft.Extensions.HostFactoryResolver.Sources , Microsoft.NETCore.BrowserDebugHost.Transport From Version 8.0.30-servicing.26367.20 -> To Version 8.0.31-servicing.26413.7 Microsoft.NETCore.App.Ref , Microsoft.NETCore.App.Runtime.win-x64 From Version 8.0.30 -> To Version 8.0.31 * Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-runtime build 20260813.15 On relative base path root Microsoft.Extensions.Caching.Memory , Microsoft.Extensions.Configuration , Microsoft.Extensions.Configuration.Abstractions , Microsoft.Extensions.Configuration.EnvironmentVariables , Microsoft.Extensions.Configuration.Json , Microsoft.Extensions.DependencyInjection , Microsoft.Extensions.DependencyModel , Microsoft.Extensions.Logging , Microsoft.NETCore.App.Ref , Microsoft.NETCore.App.Runtime.win-x64 , System.Formats.Asn1 , System.Text.Encodings.Web , System.Text.Json From Version 9.0.19 -> To Version 9.0.20 Microsoft.Extensions.HostFactoryResolver.Sources , Microsoft.NETCore.BrowserDebugHost.Transport From Version 9.0.19-servicing.26367.24 -> To Version 9.0.20-servicing.26413.15 * Update dependencies from https://dev.azure.com/dnceng/internal/_git/dotnet-runtime build 20260820.15 On relative base path root Microsoft.Extensions.HostFactoryResolver.Sources , Microsoft.NETCore.BrowserDebugHost.Transport From Version 8.0.31-servicing.26413.7 -> To Version 8.0.31-servicing.26420.15 Microsoft.NETCore.App.Ref , Microsoft.NETCore.App.Runtime.win-x64 From Version 8.0.31 -> To Version 8.0.31 * Update dependencies from https://github.com/dotnet/arcade build 20260831.8 (#38931) [release/9.0] Update dependencies from dotnet/arcade * [release/9.0]: Bump Microsoft.AspNetCore.Identity.EntityFrameworkCore from 8.0.30 to 8.0.31 (#38941) --- updated-dependencies: - dependency-name: Microsoft.AspNetCore.Identity.EntityFrameworkCore dependency-version: 8.0.31 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [release/9.0]: Bump Microsoft.Azure.Cosmos from 3.62.1 to 3.63.0 (#38942) --- updated-dependencies: - dependency-name: Microsoft.Azure.Cosmos dependency-version: 3.63.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Update dependencies from build 330600 (#38922) Updated Dependencies: Microsoft.DotNet.Arcade.Sdk, Microsoft.DotNet.Build.Tasks.Templating, Microsoft.DotNet.Helix.Sdk (Version 10.0.0-beta.26453.111 -> 10.0.0-beta.26454.107) Microsoft.Extensions.Caching.Memory, Microsoft.Extensions.Configuration, Microsoft.Extensions.Configuration.Abstractions, Microsoft.Extensions.Configuration.EnvironmentVariables, Microsoft.Extensions.Configuration.Json, Microsoft.Extensions.DependencyInjection, Microsoft.Extensions.DependencyModel, Microsoft.Extensions.Logging, Microsoft.NETCore.App.Ref, System.Formats.Asn1, System.Runtime.Caching, System.Text.Encodings.Web, System.Text.Json (Version 10.0.13 -> 10.0.13) Microsoft.Extensions.HostFactoryResolver.Sources, Microsoft.NETCore.Platforms (Version 10.0.13-servicing.26453.111 -> 10.0.13-servicing.26454.107) [[ commit created by automation ]] Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com> * [release/10.0]: Bump Microsoft.Azure.Cosmos from 3.62.1 to 3.63.0 (#38954) --- updated-dependencies: - dependency-name: Microsoft.Azure.Cosmos dependency-version: 3.63.0 dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Discard changes to Directory.Packages.props * Discard changes to NuGet.config * [release/11.0] Fix UPDATE ordering regression for unique-index reassignment (#38924) Fixes #38917 Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> * [release/11.0] Lift mixed outer-reference aggregate arguments (#38925) Fixes #38834 Co-authored-by: Ben O'Donovan <ben@whiterock.systems> Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> * [release/11.0] Fix projecting JSON complex collection together with collection navigation (#38948) Fixes #38928 Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> * Update dependencies from build 331727 (#38975) Updated Dependencies: Microsoft.DotNet.Arcade.Sdk, Microsoft.DotNet.Build.Tasks.Templating, Microsoft.DotNet.Helix.Sdk (Version 11.0.0-beta.26458.109 -> 11.0.0-beta.26461.110) Microsoft.Extensions.Caching.Memory, Microsoft.Extensions.Configuration, Microsoft.Extensions.Configuration.EnvironmentVariables, Microsoft.Extensions.Configuration.Json, Microsoft.Extensions.DependencyInjection, Microsoft.Extensions.DependencyModel, Microsoft.Extensions.HostFactoryResolver.Sources, Microsoft.Extensions.Logging, Microsoft.NETCore.App.Ref, Microsoft.NETCore.Platforms, System.Formats.Asn1, System.Runtime.Caching, System.Text.Encodings.Web, System.Text.Json (Version 11.0.0-rc.2.26458.109 -> 11.0.0-rc.2.26461.110) [[ commit created by automation ]] Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com> * [release/11.0]: Bump Microsoft.Data.SqlClient from 7.0.2 to 7.0.3 (#38968) --- updated-dependencies: - dependency-name: Microsoft.Data.SqlClient dependency-version: 7.0.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [release/11.0]: Bump Microsoft.Data.SqlClient.Extensions.Azure from 7.0.2 to 7.0.3 (#38969) --- updated-dependencies: - dependency-name: Microsoft.Data.SqlClient.Extensions.Azure dependency-version: 7.0.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [release/11.0]: Bump Microsoft.DotNet.XUnitV3Extensions from 11.0.0-beta.26454.1 to 11.0.0-beta.26461.3 (#38970) --- updated-dependencies: - dependency-name: Microsoft.DotNet.XUnitV3Extensions dependency-version: 11.0.0-beta.26461.3 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * [release/11.0]: Bump Microsoft.AspNetCore.Identity.EntityFrameworkCore from 9.0.19 to 9.0.20 (#38966) --- updated-dependencies: - dependency-name: Microsoft.AspNetCore.Identity.EntityFrameworkCore dependency-version: 9.0.20 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> * Merge pull request #38997 from dotnet/darc-release/11.0-07246f3c-4116-4837-973c-9929578ae48f [release/11.0] Source code updates from dotnet/dotnet * [release/11.0] Source code updates from dotnet/dotnet (#39003) * Update dependencies from build 332243 Updated Dependencies: Microsoft.DotNet.Arcade.Sdk, Microsoft.DotNet.Build.Tasks.Templating, Microsoft.DotNet.Helix.Sdk (Version 11.0.0-beta.26464.119 -> 11.0.0-beta.26465.108) Microsoft.Extensions.Caching.Memory, Microsoft.Extensions.Configuration, Microsoft.Extensions.Configuration.EnvironmentVariables, Microsoft.Extensions.Configuration.Json, Microsoft.Extensions.DependencyInjection, Microsoft.Extensions.DependencyModel, Microsoft.Extensions.HostFactoryResolver.Sources, Microsoft.Extensions.Logging, Microsoft.NETCore.App.Ref, Microsoft.NETCore.Platforms, System.Formats.Asn1, System.Runtime.Caching, System.Text.Encodings.Web, System.Text.Json (Version 11.0.0-rc.2.26464.119 -> 11.0.0-rc.2.26465.108) [[ commit created by automation ]] * Update dependencies from build 332290 Updated Dependencies: Microsoft.DotNet.Arcade.Sdk, Microsoft.DotNet.Build.Tasks.Templating, Microsoft.DotNet.Helix.Sdk (Version 11.0.0-beta.26465.108 -> 11.0.0-beta.26465.113) Microsoft.Extensions.Caching.Memory, Microsoft.Extensions.Configuration, Microsoft.Extensions.Configuration.EnvironmentVariables, Microsoft.Extensions.Configuration.Json, Microsoft.Extensions.DependencyInjection, Microsoft.Extensions.DependencyModel, Microsoft.Extensions.HostFactoryResolver.Sources, Microsoft.Extensions.Logging, Microsoft.NETCore.App.Ref, Microsoft.NETCore.Platforms, System.Formats.Asn1, System.Runtime.Caching, System.Text.Encodings.Web, System.Text.Json (Version 11.0.0-rc.2.26465.108 -> 11.0.0-rc.2.26465.113) [[ commit created by automation ]] --------- Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com> * [release/11.0] Source code updates from dotnet/dotnet (#39007) * Update dependencies from build 332487 Updated Dependencies: Microsoft.DotNet.Arcade.Sdk, Microsoft.DotNet.Build.Tasks.Templating, Microsoft.DotNet.Helix.Sdk (Version 11.0.0-beta.26465.113 -> 11.0.0-beta.26466.122) Microsoft.Extensions.Caching.Memory, Microsoft.Extensions.Configuration, Microsoft.Extensions.Configuration.EnvironmentVariables, Microsoft.Extensions.Configuration.Json, Microsoft.Extensions.DependencyInjection, Microsoft.Extensions.DependencyModel, Microsoft.Extensions.HostFactoryResolver.Sources, Microsoft.Extensions.Logging, Microsoft.NETCore.App.Ref, Microsoft.NETCore.Platforms, System.Formats.Asn1, System.Runtime.Caching, System.Text.Encodings.Web, System.Text.Json (Version 11.0.0-rc.2.26465.113 -> 11.0.0-rc.2.26466.122) [[ commit created by automation ]] * Update dependencies from build 332554 Updated Dependencies: Microsoft.DotNet.Arcade.Sdk, Microsoft.DotNet.Build.Tasks.Templating, Microsoft.DotNet.Helix.Sdk (Version 11.0.0-beta.26466.122 -> 11.0.0-beta.26467.104) Microsoft.Extensions.Caching.Memory, Microsoft.Extensions.Configuration, Microsoft.Extensions.Configuration.EnvironmentVariables, Microsoft.Extensions.Configuration.Json, Microsoft.Extensions.DependencyInjection, Microsoft.Extensions.DependencyModel, Microsoft.Extensions.HostFactoryResolver.Sources, Microsoft.Extensions.Logging, Microsoft.NETCore.App.Ref, Microsoft.NETCore.Platforms, System.Formats.Asn1, System.Runtime.Caching, System.Text.Encodings.Web, System.Text.Json (Version 11.0.0-rc.2.26466.122 -> 11.0.0-rc.2.26467.104) [[ commit created by automation ]] --------- Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com> --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: Mirroring <dnceng-mirroring@microsoft.com> Co-authored-by: DotNet-Bot <dn-bot@microsoft.com> Co-authored-by: Andriy Svyryd <Andriy.Svyryd@microsoft.com> Co-authored-by: ProductConstructionServiceProd <ProductConstructionServiceProd> Co-authored-by: dotnet-maestro[bot] <42748379+dotnet-maestro[bot]@users.noreply.github.com> Co-authored-by: dotnet-bot <dotnet-bot@microsoft.com> Co-authored-by: Andriy Svyryd <AndriySvyryd@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: dotnet-maestro[bot] <dotnet-maestro[bot]@users.noreply.github.com> Co-authored-by: William Godbe <wigodbe@microsoft.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> Co-authored-by: Ben O'Donovan <ben@whiterock.systems>
Fixes #38834
Port of #38855
Description
An optimization during query translation causes aggregate expressions combining an outer reference with a local column to not be lifted resulting in an error on SQL Server.
Customer impact
Affected LINQ queries fail with error 8124 when executed. There's no practical workaround.
How found
User reported on 11.0.0-rc1
Regression
Yes, from 11.0.0-preview.6. It was surfaced by PR #38502
Testing
Tests added.
Risk
Medium. While this is a relatively simple change, query changes always carry an inherent risk of affecting other scenarios.