diff --git a/src/EFCore.Relational/Query/Internal/QueryExpressionReplacingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/QueryExpressionReplacingExpressionVisitor.cs
new file mode 100644
index 00000000000..97154a73b72
--- /dev/null
+++ b/src/EFCore.Relational/Query/Internal/QueryExpressionReplacingExpressionVisitor.cs
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Diagnostics.CodeAnalysis;
+using System.Linq.Expressions;
+
+namespace Microsoft.EntityFrameworkCore.Query.Internal
+{
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ public class QueryExpressionReplacingExpressionVisitor : ExpressionVisitor
+ {
+ private readonly Expression _oldQuery;
+ private readonly Expression _newQuery;
+
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ public QueryExpressionReplacingExpressionVisitor(Expression oldQuery, Expression newQuery)
+ {
+ _oldQuery = oldQuery;
+ _newQuery = newQuery;
+ }
+
+ ///
+ /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
+ /// the same compatibility standards as public APIs. It may be changed or removed without notice in
+ /// any release. You should only use it directly in your code with extreme caution and knowing that
+ /// doing so can result in application failures when updating to a new Entity Framework Core release.
+ ///
+ [return: NotNullIfNotNull("expression")]
+ public override Expression? Visit(Expression? expression)
+ {
+ return expression is ProjectionBindingExpression projectionBindingExpression
+ && ReferenceEquals(projectionBindingExpression.QueryExpression, _oldQuery)
+ ? projectionBindingExpression.ProjectionMember != null
+ ? new ProjectionBindingExpression(
+ _newQuery, projectionBindingExpression.ProjectionMember!, projectionBindingExpression.Type)
+ : new ProjectionBindingExpression(
+ _newQuery, projectionBindingExpression.Index!.Value, projectionBindingExpression.Type)
+ : base.Visit(expression);
+ }
+ }
+}
diff --git a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs
index a690b2a13c8..a86be13667b 100644
--- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs
+++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs
@@ -3,7 +3,6 @@
using System;
using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
@@ -464,29 +463,7 @@ private static ShapedQueryExpression CreateShapedQueryExpression(IEntityType ent
source = TranslateSelect(source, elementSelector);
}
- if (translatedKey is NewExpression newExpression
- && newExpression.Arguments.Count == 0)
- {
- selectExpression.ApplyGrouping(_sqlExpressionFactory.ApplyDefaultTypeMapping(_sqlExpressionFactory.Constant(1)));
- }
- else
- {
- translatedKey = selectExpression.ApplyGrouping(translatedKey);
- }
- var clonedSelectExpression = selectExpression.Clone();
- // If the grouping key is empty then there may not be any group by terms.
- var correlationPredicate = selectExpression.GroupBy.Zip(clonedSelectExpression.GroupBy)
- .Select(e => _sqlExpressionFactory.Equal(e.First, e.Second))
- .Aggregate((l, r) => _sqlExpressionFactory.AndAlso(l, r));
- clonedSelectExpression.ClearGroupBy();
- clonedSelectExpression.ApplyPredicate(correlationPredicate);
-
- var groupByShaper = new GroupByShaperExpression(
- translatedKey,
- new ShapedQueryExpression(
- clonedSelectExpression,
- new QueryExpressionReplacingExpressionVisitor(selectExpression, clonedSelectExpression).Visit(source.ShaperExpression)));
-
+ var groupByShaper = selectExpression.ApplyGrouping(translatedKey, source.ShaperExpression, _sqlExpressionFactory);
if (resultSelector == null)
{
return source.UpdateShaperExpression(groupByShaper);
@@ -1697,30 +1674,5 @@ static void PopulatePredicateTerms(SqlExpression predicate, List
}
}
}
-
- private sealed class QueryExpressionReplacingExpressionVisitor : ExpressionVisitor
- {
- private readonly Expression _oldQuery;
- private readonly Expression _newQuery;
-
- public QueryExpressionReplacingExpressionVisitor(Expression oldQuery, Expression newQuery)
- {
- _oldQuery = oldQuery;
- _newQuery = newQuery;
- }
-
- [return: NotNullIfNotNull("expression")]
- public override Expression? Visit(Expression? expression)
- {
- return expression is ProjectionBindingExpression projectionBindingExpression
- && ReferenceEquals(projectionBindingExpression.QueryExpression, _oldQuery)
- ? projectionBindingExpression.ProjectionMember != null
- ? new ProjectionBindingExpression(
- _newQuery, projectionBindingExpression.ProjectionMember!, projectionBindingExpression.Type)
- : new ProjectionBindingExpression(
- _newQuery, projectionBindingExpression.Index!.Value, projectionBindingExpression.Type)
- : base.Visit(expression);
- }
- }
}
}
diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs
index 676ef9ce4fb..3970f041e61 100644
--- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs
+++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs
@@ -11,6 +11,7 @@
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Metadata;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
+using Microsoft.EntityFrameworkCore.Query.Internal;
using Microsoft.EntityFrameworkCore.Utilities;
namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions
@@ -1126,7 +1127,7 @@ public void ApplyPredicate(SqlExpression sqlExpression)
/// Applies grouping from given key selector.
///
/// An key selector expression for the GROUP BY.
- public Expression ApplyGrouping(Expression keySelector)
+ public void ApplyGrouping(Expression keySelector)
{
Check.NotNull(keySelector, nameof(keySelector));
@@ -1134,7 +1135,7 @@ public Expression ApplyGrouping(Expression keySelector)
var groupByTerms = new List();
var groupByAliases = new List();
- AppendGroupBy(keySelector, groupByTerms, groupByAliases, "Key");
+ PopulateGroupByTerms(keySelector, groupByTerms, groupByAliases, "Key");
if (groupByTerms.Any(e => e is SqlConstantExpression || e is SqlParameterExpression || e is ScalarSubqueryExpression))
{
@@ -1163,19 +1164,84 @@ public Expression ApplyGrouping(Expression keySelector)
_identifier.AddRange(_groupBy.Select(e => ((ColumnExpression)e, e.TypeMapping!.KeyComparer)));
}
}
-
- return keySelector;
}
///
- /// Clears existing group by terms.
+ /// Applies grouping from given key selector and generate to shape results.
///
- public void ClearGroupBy()
+ /// An key selector expression for the GROUP BY.
+ /// The shaper expression for current query.
+ /// The sql expression factory to use.
+ /// A which represents the result of the grouping operation.
+ public GroupByShaperExpression ApplyGrouping(Expression keySelector, Expression shaperExpression, ISqlExpressionFactory sqlExpressionFactory)
{
- _groupBy.Clear();
+ Check.NotNull(keySelector, nameof(keySelector));
+
+ ClearOrdering();
+
+ var keySelectorToAdd = keySelector;
+ var emptyKey = keySelector is NewExpression newExpression
+ && newExpression.Arguments.Count == 0;
+ if (emptyKey)
+ {
+ keySelectorToAdd = sqlExpressionFactory.ApplyDefaultTypeMapping(sqlExpressionFactory.Constant(1));
+ }
+
+ var groupByTerms = new List();
+ var groupByAliases = new List();
+ PopulateGroupByTerms(keySelectorToAdd, groupByTerms, groupByAliases, "Key");
+
+ if (groupByTerms.Any(e => e is SqlConstantExpression || e is SqlParameterExpression || e is ScalarSubqueryExpression))
+ {
+ // EmptyKey will always hit this path.
+ var sqlRemappingVisitor = PushdownIntoSubqueryInternal();
+ var newGroupByTerms = new List(groupByTerms.Count);
+ var subquery = (SelectExpression)_tables[0];
+ var subqueryTableReference = _tableReferences[0];
+ for (var i = 0; i < groupByTerms.Count; i++)
+ {
+ var item = groupByTerms[i];
+ var newItem = subquery._projection.Any(e => e.Expression.Equals(item))
+ ? sqlRemappingVisitor.Remap(item)
+ : subquery.GenerateOuterColumn(subqueryTableReference, item, groupByAliases[i] ?? "Key");
+ newGroupByTerms.Add(newItem);
+ }
+ if (!emptyKey)
+ {
+ // If non-empty key then we need to regenerate the key selector
+ keySelector = new ReplacingExpressionVisitor(groupByTerms, newGroupByTerms).Visit(keySelector);
+ }
+ groupByTerms = newGroupByTerms;
+ }
+
+ _groupBy.AddRange(groupByTerms);
+
+ // We generate the cloned expression before changing identifier for this SelectExpression
+ // because we are going to erase grouping for cloned expression.
+ var clonedSelectExpression = Clone();
+ var correlationPredicate = groupByTerms.Zip(clonedSelectExpression._groupBy)
+ .Select(e => sqlExpressionFactory.Equal(e.First, e.Second))
+ .Aggregate((l, r) => sqlExpressionFactory.AndAlso(l, r));
+ clonedSelectExpression._groupBy.Clear();
+ clonedSelectExpression.ApplyPredicate(correlationPredicate);
+
+ if (!_identifier.All(e => _groupBy.Contains(e.Column)))
+ {
+ _identifier.Clear();
+ if (_groupBy.All(e => e is ColumnExpression))
+ {
+ _identifier.AddRange(_groupBy.Select(e => ((ColumnExpression)e, e.TypeMapping!.KeyComparer)));
+ }
+ }
+
+ return new GroupByShaperExpression(
+ keySelector,
+ new ShapedQueryExpression(
+ clonedSelectExpression,
+ new QueryExpressionReplacingExpressionVisitor(this, clonedSelectExpression).Visit(shaperExpression)));
}
- private void AppendGroupBy(Expression keySelector, List groupByTerms, List groupByAliases, string? name)
+ private void PopulateGroupByTerms(Expression keySelector, List groupByTerms, List groupByAliases, string? name)
{
Check.NotNull(keySelector, nameof(keySelector));
@@ -1189,23 +1255,23 @@ private void AppendGroupBy(Expression keySelector, List groupByTe
case NewExpression newExpression:
for (var i = 0; i < newExpression.Arguments.Count; i++)
{
- AppendGroupBy(newExpression.Arguments[i], groupByTerms, groupByAliases, newExpression.Members?[i].Name);
+ PopulateGroupByTerms(newExpression.Arguments[i], groupByTerms, groupByAliases, newExpression.Members?[i].Name);
}
break;
case MemberInitExpression memberInitExpression:
- AppendGroupBy(memberInitExpression.NewExpression, groupByTerms, groupByAliases, null);
+ PopulateGroupByTerms(memberInitExpression.NewExpression, groupByTerms, groupByAliases, null);
foreach (var argument in memberInitExpression.Bindings)
{
var memberAssignment = (MemberAssignment)argument;
- AppendGroupBy(memberAssignment.Expression, groupByTerms, groupByAliases, memberAssignment.Member.Name);
+ PopulateGroupByTerms(memberAssignment.Expression, groupByTerms, groupByAliases, memberAssignment.Member.Name);
}
break;
case UnaryExpression unaryExpression
when unaryExpression.NodeType == ExpressionType.Convert
|| unaryExpression.NodeType == ExpressionType.ConvertChecked:
- AppendGroupBy(unaryExpression.Operand, groupByTerms, groupByAliases, name);
+ PopulateGroupByTerms(unaryExpression.Operand, groupByTerms, groupByAliases, name);
break;
default:
diff --git a/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.ExpressionVisitors.cs b/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.ExpressionVisitors.cs
index d1977373693..cb2ed4fda42 100644
--- a/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.ExpressionVisitors.cs
+++ b/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.ExpressionVisitors.cs
@@ -1195,7 +1195,9 @@ public GroupingElementReplacingExpressionVisitor(
protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression)
{
if (methodCallExpression.Method.IsGenericMethod
- && methodCallExpression.Method.GetGenericMethodDefinition() == QueryableMethods.AsQueryable
+ && (methodCallExpression.Method.GetGenericMethodDefinition() == QueryableMethods.AsQueryable
+ || methodCallExpression.Method.GetGenericMethodDefinition() == EnumerableMethods.ToList
+ || methodCallExpression.Method.GetGenericMethodDefinition() == EnumerableMethods.ToArray)
&& methodCallExpression.Arguments[0] == _parameterExpression)
{
var currentTree = _cloningExpressionVisitor.Clone(_navigationExpansionExpression.CurrentTree);
diff --git a/test/EFCore.Specification.Tests/Query/NorthwindGroupByQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/NorthwindGroupByQueryTestBase.cs
index b814c7bd6f5..1618e573add 100644
--- a/test/EFCore.Specification.Tests/Query/NorthwindGroupByQueryTestBase.cs
+++ b/test/EFCore.Specification.Tests/Query/NorthwindGroupByQueryTestBase.cs
@@ -436,6 +436,17 @@ from c in grouping.DefaultIfEmpty()
g => new { Value = g.Key + g.Key, Average = g.Average(o => o.OrderID) }));
}
+ [ConditionalTheory]
+ [MemberData(nameof(IsAsyncData))]
+ public virtual Task GroupBy_with_aggregate_through_navigation_property(bool async)
+ {
+ return AssertQuery(
+ async,
+ ss => ss.Set().GroupBy(c => c.EmployeeID).Select(
+ g => new { max = g.Max(i => i.Customer.Region) }),
+ elementSorter: e => e.max);
+ }
+
#endregion
#region GroupByAnonymousAggregate
@@ -1909,7 +1920,7 @@ from o in ss.Set().GroupBy(o => o.CustomerID)
.Where(g => g.Count() > 5)
.Select(g => new { CustomerID = g.Key, LastOrderID = g.Max(o => o.OrderID) })
.Where(c1 => c.CustomerID == c1.CustomerID)
- select c,
+ select c,
entryCount: 63);
}
@@ -2833,17 +2844,6 @@ public virtual Task GroupBy_Distinct(bool async)
ss => ss.Set().GroupBy(o => o.CustomerID).Distinct().Select(g => g.Key)));
}
- [ConditionalTheory]
- [MemberData(nameof(IsAsyncData))]
- public virtual Task GroupBy_with_aggregate_through_navigation_property(bool async)
- {
- return AssertQuery(
- async,
- ss => ss.Set().GroupBy(c => c.EmployeeID).Select(
- g => new { max = g.Max(i => i.Customer.Region) }),
- elementSorter: e => e.max);
- }
-
#endregion
#region GroupBySelectFirst
@@ -2882,6 +2882,78 @@ public virtual Task GroupBy_Shadow3(bool async)
.Select(g => EF.Property(g.First(), "Title")));
}
+ [ConditionalTheory]
+ [MemberData(nameof(IsAsyncData))]
+ public virtual Task GroupBy_select_grouping_list(bool async)
+ {
+ return AssertQuery(
+ async,
+ ss => ss.Set()
+ .GroupBy(e => e.City)
+ .Select(g => new { g.Key, List = g.ToList() }),
+ elementSorter: e => e.Key,
+ elementAsserter: (e, a) =>
+ {
+ AssertEqual(e.Key, a.Key);
+ AssertCollection(e.List, a.List);
+ },
+ entryCount: 91);
+ }
+
+ [ConditionalTheory]
+ [MemberData(nameof(IsAsyncData))]
+ public virtual Task GroupBy_select_grouping_array(bool async)
+ {
+ return AssertQuery(
+ async,
+ ss => ss.Set()
+ .GroupBy(e => e.City)
+ .Select(g => new { g.Key, List = g.ToArray() }),
+ elementSorter: e => e.Key,
+ elementAsserter: (e, a) =>
+ {
+ AssertEqual(e.Key, a.Key);
+ AssertCollection(e.List, a.List);
+ },
+ entryCount: 91);
+ }
+
+ [ConditionalTheory]
+ [MemberData(nameof(IsAsyncData))]
+ public virtual Task GroupBy_select_grouping_composed_list(bool async)
+ {
+ return AssertQuery(
+ async,
+ ss => ss.Set()
+ .GroupBy(e => e.City)
+ .Select(g => new { g.Key, List = g.Where(c => c.CustomerID.StartsWith("A")).ToList() }),
+ elementSorter: e => e.Key,
+ elementAsserter: (e, a) =>
+ {
+ AssertEqual(e.Key, a.Key);
+ AssertCollection(e.List, a.List);
+ },
+ entryCount: 4);
+ }
+
+ [ConditionalTheory]
+ [MemberData(nameof(IsAsyncData))]
+ public virtual Task GroupBy_select_grouping_composed_list_2(bool async)
+ {
+ return AssertQuery(
+ async,
+ ss => ss.Set()
+ .GroupBy(e => e.City)
+ .Select(g => new { g.Key, List = g.OrderBy(c => c.CustomerID).ToList() }),
+ elementSorter: e => e.Key,
+ elementAsserter: (e, a) =>
+ {
+ AssertEqual(e.Key, a.Key);
+ AssertCollection(e.List, a.List);
+ },
+ entryCount: 91);
+ }
+
#endregion
#region GroupByEntityType
diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqlServerTest.cs
index 85e4874710e..356ebcdac45 100644
--- a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqlServerTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsQuerySqlServerTest.cs
@@ -661,7 +661,7 @@ FROM [LevelOne] AS [l0]
WHERE [t1].[row] <= 1
) AS [t0] ON [t].[Name] = [t0].[Name]
LEFT JOIN [LevelTwo] AS [l1] ON [t0].[Id] = [l1].[OneToMany_Optional_Inverse2Id]
-ORDER BY [t].[Name], [t0].[Name]");
+ORDER BY [t].[Name], [t0].[Id]");
}
public override async Task Include_collection_with_groupby_in_subquery_and_filter_before_groupby(bool async)
@@ -686,7 +686,7 @@ WHERE [l0].[Id] > 3
WHERE [t1].[row] <= 1
) AS [t0] ON [t].[Name] = [t0].[Name]
LEFT JOIN [LevelTwo] AS [l1] ON [t0].[Id] = [l1].[OneToMany_Optional_Inverse2Id]
-ORDER BY [t].[Name], [t0].[Name]");
+ORDER BY [t].[Name], [t0].[Id]");
}
public override async Task Include_collection_with_groupby_in_subquery_and_filter_after_groupby(bool async)
@@ -710,7 +710,7 @@ FROM [LevelOne] AS [l0]
WHERE [t1].[row] <= 1
) AS [t0] ON [t].[Name] = [t0].[Name]
LEFT JOIN [LevelTwo] AS [l1] ON [t0].[Id] = [l1].[OneToMany_Optional_Inverse2Id]
-ORDER BY [t].[Name], [t0].[Name]");
+ORDER BY [t].[Name], [t0].[Id]");
}
public override async Task Include_reference_collection_order_by_reference_navigation(bool async)
@@ -2000,16 +2000,16 @@ public override async Task Skip_Take_on_grouping_element_into_non_entity(bool as
await base.Skip_Take_on_grouping_element_into_non_entity(async);
AssertSql(
- @"SELECT [t].[Date], [t0].[Name], [t0].[Date]
+ @"SELECT [t].[Date], [t0].[Name], [t0].[Id]
FROM (
SELECT [l].[Date]
FROM [LevelOne] AS [l]
GROUP BY [l].[Date]
) AS [t]
LEFT JOIN (
- SELECT [t1].[Name], [t1].[Date]
+ SELECT [t1].[Name], [t1].[Id], [t1].[Date]
FROM (
- SELECT [l0].[Name], [l0].[Date], ROW_NUMBER() OVER(PARTITION BY [l0].[Date] ORDER BY [l0].[Name]) AS [row]
+ SELECT [l0].[Name], [l0].[Id], [l0].[Date], ROW_NUMBER() OVER(PARTITION BY [l0].[Date] ORDER BY [l0].[Name]) AS [row]
FROM [LevelOne] AS [l0]
) AS [t1]
WHERE (1 < [t1].[row]) AND ([t1].[row] <= 6)
@@ -2039,7 +2039,7 @@ OFFSET 1 ROWS FETCH NEXT 5 ROWS ONLY
) AS [t1]
LEFT JOIN [LevelTwo] AS [l0] ON [t1].[Id] = [l0].[OneToMany_Optional_Inverse2Id]
) AS [t0]
-ORDER BY [t].[Date], [t0].[Name], [t0].[Date]");
+ORDER BY [t].[Date], [t0].[Name], [t0].[Id]");
}
public override async Task Skip_Take_on_grouping_element_with_reference_include(bool async)
@@ -2064,7 +2064,7 @@ OFFSET 1 ROWS FETCH NEXT 5 ROWS ONLY
) AS [t1]
LEFT JOIN [LevelTwo] AS [l0] ON [t1].[Id] = [l0].[Level1_Optional_Id]
) AS [t0]
-ORDER BY [t].[Date], [t0].[Name], [t0].[Date]");
+ORDER BY [t].[Date], [t0].[Name], [t0].[Id]");
}
public override async Task Skip_Take_on_grouping_element_inside_collection_projection(bool async)
diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqlServerTest.cs
index 58a87f74eec..509624571d8 100644
--- a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqlServerTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsCollectionsSplitQuerySqlServerTest.cs
@@ -2228,9 +2228,9 @@ FROM [LevelOne] AS [l0]
) AS [t1]
WHERE [t1].[row] <= 1
) AS [t0] ON [t].[Name] = [t0].[Name]
-ORDER BY [t].[Name], [t0].[Name]",
+ORDER BY [t].[Name], [t0].[Id]",
//
- @"SELECT [l1].[Id], [l1].[Date], [l1].[Level1_Optional_Id], [l1].[Level1_Required_Id], [l1].[Name], [l1].[OneToMany_Optional_Inverse2Id], [l1].[OneToMany_Optional_Self_Inverse2Id], [l1].[OneToMany_Required_Inverse2Id], [l1].[OneToMany_Required_Self_Inverse2Id], [l1].[OneToOne_Optional_PK_Inverse2Id], [l1].[OneToOne_Optional_Self2Id], [t].[Name], [t0].[Name]
+ @"SELECT [l1].[Id], [l1].[Date], [l1].[Level1_Optional_Id], [l1].[Level1_Required_Id], [l1].[Name], [l1].[OneToMany_Optional_Inverse2Id], [l1].[OneToMany_Optional_Self_Inverse2Id], [l1].[OneToMany_Required_Inverse2Id], [l1].[OneToMany_Required_Self_Inverse2Id], [l1].[OneToOne_Optional_PK_Inverse2Id], [l1].[OneToOne_Optional_Self2Id], [t].[Name], [t0].[Id]
FROM (
SELECT [l].[Name]
FROM [LevelOne] AS [l]
@@ -2245,7 +2245,7 @@ FROM [LevelOne] AS [l0]
WHERE [t1].[row] <= 1
) AS [t0] ON [t].[Name] = [t0].[Name]
INNER JOIN [LevelTwo] AS [l1] ON [t0].[Id] = [l1].[OneToMany_Optional_Inverse2Id]
-ORDER BY [t].[Name], [t0].[Name]");
+ORDER BY [t].[Name], [t0].[Id]");
}
public override async Task Include_collection_with_groupby_in_subquery_and_filter_before_groupby(bool async)
@@ -2269,9 +2269,9 @@ WHERE [l0].[Id] > 3
) AS [t1]
WHERE [t1].[row] <= 1
) AS [t0] ON [t].[Name] = [t0].[Name]
-ORDER BY [t].[Name], [t0].[Name]",
+ORDER BY [t].[Name], [t0].[Id]",
//
- @"SELECT [l1].[Id], [l1].[Date], [l1].[Level1_Optional_Id], [l1].[Level1_Required_Id], [l1].[Name], [l1].[OneToMany_Optional_Inverse2Id], [l1].[OneToMany_Optional_Self_Inverse2Id], [l1].[OneToMany_Required_Inverse2Id], [l1].[OneToMany_Required_Self_Inverse2Id], [l1].[OneToOne_Optional_PK_Inverse2Id], [l1].[OneToOne_Optional_Self2Id], [t].[Name], [t0].[Name]
+ @"SELECT [l1].[Id], [l1].[Date], [l1].[Level1_Optional_Id], [l1].[Level1_Required_Id], [l1].[Name], [l1].[OneToMany_Optional_Inverse2Id], [l1].[OneToMany_Optional_Self_Inverse2Id], [l1].[OneToMany_Required_Inverse2Id], [l1].[OneToMany_Required_Self_Inverse2Id], [l1].[OneToOne_Optional_PK_Inverse2Id], [l1].[OneToOne_Optional_Self2Id], [t].[Name], [t0].[Id]
FROM (
SELECT [l].[Name]
FROM [LevelOne] AS [l]
@@ -2288,7 +2288,7 @@ WHERE [l0].[Id] > 3
WHERE [t1].[row] <= 1
) AS [t0] ON [t].[Name] = [t0].[Name]
INNER JOIN [LevelTwo] AS [l1] ON [t0].[Id] = [l1].[OneToMany_Optional_Inverse2Id]
-ORDER BY [t].[Name], [t0].[Name]");
+ORDER BY [t].[Name], [t0].[Id]");
}
public override async Task Include_collection_with_groupby_in_subquery_and_filter_after_groupby(bool async)
@@ -2311,9 +2311,9 @@ FROM [LevelOne] AS [l0]
) AS [t1]
WHERE [t1].[row] <= 1
) AS [t0] ON [t].[Name] = [t0].[Name]
-ORDER BY [t].[Name], [t0].[Name]",
+ORDER BY [t].[Name], [t0].[Id]",
//
- @"SELECT [l1].[Id], [l1].[Date], [l1].[Level1_Optional_Id], [l1].[Level1_Required_Id], [l1].[Name], [l1].[OneToMany_Optional_Inverse2Id], [l1].[OneToMany_Optional_Self_Inverse2Id], [l1].[OneToMany_Required_Inverse2Id], [l1].[OneToMany_Required_Self_Inverse2Id], [l1].[OneToOne_Optional_PK_Inverse2Id], [l1].[OneToOne_Optional_Self2Id], [t].[Name], [t0].[Name]
+ @"SELECT [l1].[Id], [l1].[Date], [l1].[Level1_Optional_Id], [l1].[Level1_Required_Id], [l1].[Name], [l1].[OneToMany_Optional_Inverse2Id], [l1].[OneToMany_Optional_Self_Inverse2Id], [l1].[OneToMany_Required_Inverse2Id], [l1].[OneToMany_Required_Self_Inverse2Id], [l1].[OneToOne_Optional_PK_Inverse2Id], [l1].[OneToOne_Optional_Self2Id], [t].[Name], [t0].[Id]
FROM (
SELECT [l].[Name]
FROM [LevelOne] AS [l]
@@ -2329,7 +2329,7 @@ FROM [LevelOne] AS [l0]
WHERE [t1].[row] <= 1
) AS [t0] ON [t].[Name] = [t0].[Name]
INNER JOIN [LevelTwo] AS [l1] ON [t0].[Id] = [l1].[OneToMany_Optional_Inverse2Id]
-ORDER BY [t].[Name], [t0].[Name]");
+ORDER BY [t].[Name], [t0].[Id]");
}
public override async Task Include_reference_collection_order_by_reference_navigation(bool async)
@@ -3111,7 +3111,7 @@ FROM [LevelOne] AS [l0]
) AS [t1]
WHERE (1 < [t1].[row]) AND ([t1].[row] <= 6)
) AS [t0] ON [t].[Date] = [t0].[Date]
-ORDER BY [t].[Date], [t0].[Date], [t0].[Name]");
+ORDER BY [t].[Date], [t0].[Date], [t0].[Name], [t0].[Id]");
}
public override async Task Skip_Take_on_grouping_element_with_reference_include(bool async)
diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServerTest.cs
index ba668023866..f76c3ca9b08 100644
--- a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServerTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServerTest.cs
@@ -2611,7 +2611,7 @@ FROM [LevelOne] AS [l0]
WHERE [t1].[row] <= 1
) AS [t0] ON [t].[Name] = [t0].[Name]
LEFT JOIN [LevelThree] AS [l2] ON [t0].[Id0] = [l2].[OneToMany_Optional_Inverse3Id]
-ORDER BY [t].[Name], [t0].[Name], [t0].[Id0]");
+ORDER BY [t].[Name], [t0].[Id], [t0].[Id0]");
}
public override async Task String_include_multiple_derived_navigation_with_same_name_and_same_type(bool async)
diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs
index d7d70fd8348..91227850ccf 100644
--- a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs
@@ -5589,7 +5589,7 @@ GROUP BY [g].[Rank]
LEFT JOIN (
SELECT [t1].[Nickname], [t1].[SquadId], [t1].[AssignedCityName], [t1].[CityOfBirthName], [t1].[Discriminator], [t1].[FullName], [t1].[HasSoulPatch], [t1].[LeaderNickname], [t1].[LeaderSquadId], [t1].[Rank], [t1].[Name], [t1].[Location], [t1].[Nation]
FROM (
- SELECT [g0].[Nickname], [g0].[SquadId], [g0].[AssignedCityName], [g0].[CityOfBirthName], [g0].[Discriminator], [g0].[FullName], [g0].[HasSoulPatch], [g0].[LeaderNickname], [g0].[LeaderSquadId], [g0].[Rank], [c].[Name], [c].[Location], [c].[Nation], ROW_NUMBER() OVER(PARTITION BY [g0].[Rank] ORDER BY [g0].[Rank], [c].[Name]) AS [row]
+ SELECT [g0].[Nickname], [g0].[SquadId], [g0].[AssignedCityName], [g0].[CityOfBirthName], [g0].[Discriminator], [g0].[FullName], [g0].[HasSoulPatch], [g0].[LeaderNickname], [g0].[LeaderSquadId], [g0].[Rank], [c].[Name], [c].[Location], [c].[Nation], ROW_NUMBER() OVER(PARTITION BY [g0].[Rank] ORDER BY [g0].[Nickname], [g0].[SquadId], [c].[Name]) AS [row]
FROM [Gears] AS [g0]
INNER JOIN [Cities] AS [c] ON [g0].[CityOfBirthName] = [c].[Name]
WHERE [g0].[HasSoulPatch] = CAST(1 AS bit)
diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindGroupByQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindGroupByQuerySqlServerTest.cs
index 1a474be074f..3e5f589eb62 100644
--- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindGroupByQuerySqlServerTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindGroupByQuerySqlServerTest.cs
@@ -1893,7 +1893,7 @@ GROUP BY [e].[Title]
LEFT JOIN (
SELECT [t1].[EmployeeID], [t1].[City], [t1].[Country], [t1].[FirstName], [t1].[ReportsTo], [t1].[Title]
FROM (
- SELECT [e0].[EmployeeID], [e0].[City], [e0].[Country], [e0].[FirstName], [e0].[ReportsTo], [e0].[Title], ROW_NUMBER() OVER(PARTITION BY [e0].[Title] ORDER BY [e0].[Title]) AS [row]
+ SELECT [e0].[EmployeeID], [e0].[City], [e0].[Country], [e0].[FirstName], [e0].[ReportsTo], [e0].[Title], ROW_NUMBER() OVER(PARTITION BY [e0].[Title] ORDER BY [e0].[EmployeeID]) AS [row]
FROM [Employees] AS [e0]
WHERE ([e0].[Title] = N'Sales Representative') AND ([e0].[EmployeeID] = 1)
) AS [t1]
@@ -1915,6 +1915,74 @@ FROM [Employees] AS [e]
GROUP BY [e].[EmployeeID]");
}
+ public override async Task GroupBy_select_grouping_list(bool async)
+ {
+ await base.GroupBy_select_grouping_list(async);
+
+ AssertSql(
+ @"SELECT [t].[City], [c0].[CustomerID], [c0].[Address], [c0].[City], [c0].[CompanyName], [c0].[ContactName], [c0].[ContactTitle], [c0].[Country], [c0].[Fax], [c0].[Phone], [c0].[PostalCode], [c0].[Region]
+FROM (
+ SELECT [c].[City]
+ FROM [Customers] AS [c]
+ GROUP BY [c].[City]
+) AS [t]
+LEFT JOIN [Customers] AS [c0] ON [t].[City] = [c0].[City]
+ORDER BY [t].[City]");
+ }
+
+ public override async Task GroupBy_select_grouping_array(bool async)
+ {
+ await base.GroupBy_select_grouping_array(async);
+
+ AssertSql(
+ @"SELECT [t].[City], [c0].[CustomerID], [c0].[Address], [c0].[City], [c0].[CompanyName], [c0].[ContactName], [c0].[ContactTitle], [c0].[Country], [c0].[Fax], [c0].[Phone], [c0].[PostalCode], [c0].[Region]
+FROM (
+ SELECT [c].[City]
+ FROM [Customers] AS [c]
+ GROUP BY [c].[City]
+) AS [t]
+LEFT JOIN [Customers] AS [c0] ON [t].[City] = [c0].[City]
+ORDER BY [t].[City]");
+ }
+
+ public override async Task GroupBy_select_grouping_composed_list(bool async)
+ {
+ await base.GroupBy_select_grouping_composed_list(async);
+
+ AssertSql(
+ @"SELECT [t].[City], [t0].[CustomerID], [t0].[Address], [t0].[City], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Country], [t0].[Fax], [t0].[Phone], [t0].[PostalCode], [t0].[Region]
+FROM (
+ SELECT [c].[City]
+ FROM [Customers] AS [c]
+ GROUP BY [c].[City]
+) AS [t]
+LEFT JOIN (
+ SELECT [c0].[CustomerID], [c0].[Address], [c0].[City], [c0].[CompanyName], [c0].[ContactName], [c0].[ContactTitle], [c0].[Country], [c0].[Fax], [c0].[Phone], [c0].[PostalCode], [c0].[Region]
+ FROM [Customers] AS [c0]
+ WHERE [c0].[CustomerID] LIKE N'A%'
+) AS [t0] ON ([t].[City] = [t0].[City]) OR ([t].[City] IS NULL AND [t0].[City] IS NULL)
+ORDER BY [t].[City]");
+ }
+
+ public override async Task GroupBy_select_grouping_composed_list_2(bool async)
+ {
+ await base.GroupBy_select_grouping_composed_list_2(async);
+
+ AssertSql(
+ @"SELECT [t].[City], [t0].[CustomerID], [t0].[Address], [t0].[City], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Country], [t0].[Fax], [t0].[Phone], [t0].[PostalCode], [t0].[Region]
+FROM (
+ SELECT [c].[City]
+ FROM [Customers] AS [c]
+ GROUP BY [c].[City]
+) AS [t]
+LEFT JOIN (
+ SELECT [c0].[CustomerID], [c0].[Address], [c0].[City], [c0].[CompanyName], [c0].[ContactName], [c0].[ContactTitle], [c0].[Country], [c0].[Fax], [c0].[Phone], [c0].[PostalCode], [c0].[Region]
+ FROM [Customers] AS [c0]
+) AS [t0] ON [t].[City] = [t0].[City]
+ORDER BY [t].[City], [t0].[CustomerID]");
+ }
+
+
public override async Task Select_GroupBy_SelectMany(bool async)
{
await base.Select_GroupBy_SelectMany(async);
diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindIncludeQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindIncludeQuerySqlServerTest.cs
index dc3d1e44671..f38630ac6cd 100644
--- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindIncludeQuerySqlServerTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindIncludeQuerySqlServerTest.cs
@@ -1097,7 +1097,7 @@ public override async Task Include_collection_Join_GroupBy_Select(bool async)
await base.Include_collection_Join_GroupBy_Select(async);
AssertSql(
- @"SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t].[OrderID], [o3].[OrderID], [o3].[ProductID], [o3].[Discount], [o3].[Quantity], [o3].[UnitPrice]
+ @"SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t].[OrderID], [t0].[OrderID0], [t0].[ProductID], [o3].[OrderID], [o3].[ProductID], [o3].[Discount], [o3].[Quantity], [o3].[UnitPrice]
FROM (
SELECT [o].[OrderID]
FROM [Orders] AS [o]
@@ -1106,9 +1106,9 @@ FROM [Orders] AS [o]
GROUP BY [o].[OrderID]
) AS [t]
LEFT JOIN (
- SELECT [t1].[OrderID], [t1].[CustomerID], [t1].[EmployeeID], [t1].[OrderDate]
+ SELECT [t1].[OrderID], [t1].[CustomerID], [t1].[EmployeeID], [t1].[OrderDate], [t1].[OrderID0], [t1].[ProductID]
FROM (
- SELECT [o1].[OrderID], [o1].[CustomerID], [o1].[EmployeeID], [o1].[OrderDate], ROW_NUMBER() OVER(PARTITION BY [o1].[OrderID] ORDER BY [o1].[OrderID]) AS [row]
+ SELECT [o1].[OrderID], [o1].[CustomerID], [o1].[EmployeeID], [o1].[OrderDate], [o2].[OrderID] AS [OrderID0], [o2].[ProductID], ROW_NUMBER() OVER(PARTITION BY [o1].[OrderID] ORDER BY [o1].[OrderID]) AS [row]
FROM [Orders] AS [o1]
INNER JOIN [Order Details] AS [o2] ON [o1].[OrderID] = [o2].[OrderID]
WHERE [o1].[OrderID] = 10248
@@ -1116,7 +1116,7 @@ FROM [Orders] AS [o1]
WHERE [t1].[row] <= 1
) AS [t0] ON [t].[OrderID] = [t0].[OrderID]
LEFT JOIN [Order Details] AS [o3] ON [t0].[OrderID] = [o3].[OrderID]
-ORDER BY [t].[OrderID], [t0].[OrderID], [o3].[OrderID]");
+ORDER BY [t].[OrderID], [t0].[OrderID], [t0].[OrderID0], [t0].[ProductID], [o3].[OrderID]");
}
public override async Task Include_reference_Join_GroupBy_Select(bool async)
@@ -1150,7 +1150,7 @@ public override async Task Join_Include_collection_GroupBy_Select(bool async)
await base.Join_Include_collection_GroupBy_Select(async);
AssertSql(
- @"SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t].[OrderID], [o3].[OrderID], [o3].[ProductID], [o3].[Discount], [o3].[Quantity], [o3].[UnitPrice]
+ @"SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t].[OrderID], [t0].[OrderID0], [t0].[ProductID], [o3].[OrderID], [o3].[ProductID], [o3].[Discount], [o3].[Quantity], [o3].[UnitPrice]
FROM (
SELECT [o0].[OrderID]
FROM [Order Details] AS [o]
@@ -1159,9 +1159,9 @@ FROM [Order Details] AS [o]
GROUP BY [o0].[OrderID]
) AS [t]
LEFT JOIN (
- SELECT [t1].[OrderID], [t1].[CustomerID], [t1].[EmployeeID], [t1].[OrderDate]
+ SELECT [t1].[OrderID], [t1].[CustomerID], [t1].[EmployeeID], [t1].[OrderDate], [t1].[OrderID0], [t1].[ProductID]
FROM (
- SELECT [o2].[OrderID], [o2].[CustomerID], [o2].[EmployeeID], [o2].[OrderDate], ROW_NUMBER() OVER(PARTITION BY [o2].[OrderID] ORDER BY [o2].[OrderID]) AS [row]
+ SELECT [o2].[OrderID], [o2].[CustomerID], [o2].[EmployeeID], [o2].[OrderDate], [o1].[OrderID] AS [OrderID0], [o1].[ProductID], ROW_NUMBER() OVER(PARTITION BY [o2].[OrderID] ORDER BY [o2].[OrderID]) AS [row]
FROM [Order Details] AS [o1]
INNER JOIN [Orders] AS [o2] ON [o1].[OrderID] = [o2].[OrderID]
WHERE [o1].[OrderID] = 10248
@@ -1169,7 +1169,7 @@ FROM [Order Details] AS [o1]
WHERE [t1].[row] <= 1
) AS [t0] ON [t].[OrderID] = [t0].[OrderID]
LEFT JOIN [Order Details] AS [o3] ON [t0].[OrderID] = [o3].[OrderID]
-ORDER BY [t].[OrderID], [t0].[OrderID], [o3].[OrderID]");
+ORDER BY [t].[OrderID], [t0].[OrderID0], [t0].[ProductID], [t0].[OrderID], [o3].[OrderID]");
}
public override async Task Join_Include_reference_GroupBy_Select(bool async)
@@ -1201,7 +1201,7 @@ public override async Task Include_collection_SelectMany_GroupBy_Select(bool asy
await base.Include_collection_SelectMany_GroupBy_Select(async);
AssertSql(
- @"SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t].[OrderID], [o3].[OrderID], [o3].[ProductID], [o3].[Discount], [o3].[Quantity], [o3].[UnitPrice]
+ @"SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t].[OrderID], [t0].[OrderID0], [t0].[ProductID], [o3].[OrderID], [o3].[ProductID], [o3].[Discount], [o3].[Quantity], [o3].[UnitPrice]
FROM (
SELECT [o].[OrderID]
FROM [Orders] AS [o]
@@ -1210,9 +1210,9 @@ CROSS JOIN [Order Details] AS [o0]
GROUP BY [o].[OrderID]
) AS [t]
LEFT JOIN (
- SELECT [t1].[OrderID], [t1].[CustomerID], [t1].[EmployeeID], [t1].[OrderDate]
+ SELECT [t1].[OrderID], [t1].[CustomerID], [t1].[EmployeeID], [t1].[OrderDate], [t1].[OrderID0], [t1].[ProductID]
FROM (
- SELECT [o1].[OrderID], [o1].[CustomerID], [o1].[EmployeeID], [o1].[OrderDate], ROW_NUMBER() OVER(PARTITION BY [o1].[OrderID] ORDER BY [o1].[OrderID]) AS [row]
+ SELECT [o1].[OrderID], [o1].[CustomerID], [o1].[EmployeeID], [o1].[OrderDate], [o2].[OrderID] AS [OrderID0], [o2].[ProductID], ROW_NUMBER() OVER(PARTITION BY [o1].[OrderID] ORDER BY [o1].[OrderID]) AS [row]
FROM [Orders] AS [o1]
CROSS JOIN [Order Details] AS [o2]
WHERE [o1].[OrderID] = 10248
@@ -1220,7 +1220,7 @@ CROSS JOIN [Order Details] AS [o2]
WHERE [t1].[row] <= 1
) AS [t0] ON [t].[OrderID] = [t0].[OrderID]
LEFT JOIN [Order Details] AS [o3] ON [t0].[OrderID] = [o3].[OrderID]
-ORDER BY [t].[OrderID], [t0].[OrderID], [o3].[OrderID]");
+ORDER BY [t].[OrderID], [t0].[OrderID], [t0].[OrderID0], [t0].[ProductID], [o3].[OrderID]");
}
public override async Task Include_reference_SelectMany_GroupBy_Select(bool async)
@@ -1254,7 +1254,7 @@ public override async Task SelectMany_Include_collection_GroupBy_Select(bool asy
await base.SelectMany_Include_collection_GroupBy_Select(async);
AssertSql(
- @"SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t].[OrderID], [o3].[OrderID], [o3].[ProductID], [o3].[Discount], [o3].[Quantity], [o3].[UnitPrice]
+ @"SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t].[OrderID], [t0].[OrderID0], [t0].[ProductID], [o3].[OrderID], [o3].[ProductID], [o3].[Discount], [o3].[Quantity], [o3].[UnitPrice]
FROM (
SELECT [o0].[OrderID]
FROM [Order Details] AS [o]
@@ -1263,9 +1263,9 @@ CROSS JOIN [Orders] AS [o0]
GROUP BY [o0].[OrderID]
) AS [t]
LEFT JOIN (
- SELECT [t1].[OrderID], [t1].[CustomerID], [t1].[EmployeeID], [t1].[OrderDate]
+ SELECT [t1].[OrderID], [t1].[CustomerID], [t1].[EmployeeID], [t1].[OrderDate], [t1].[OrderID0], [t1].[ProductID]
FROM (
- SELECT [o2].[OrderID], [o2].[CustomerID], [o2].[EmployeeID], [o2].[OrderDate], ROW_NUMBER() OVER(PARTITION BY [o2].[OrderID] ORDER BY [o2].[OrderID]) AS [row]
+ SELECT [o2].[OrderID], [o2].[CustomerID], [o2].[EmployeeID], [o2].[OrderDate], [o1].[OrderID] AS [OrderID0], [o1].[ProductID], ROW_NUMBER() OVER(PARTITION BY [o2].[OrderID] ORDER BY [o2].[OrderID]) AS [row]
FROM [Order Details] AS [o1]
CROSS JOIN [Orders] AS [o2]
WHERE [o1].[OrderID] = 10248
@@ -1273,7 +1273,7 @@ CROSS JOIN [Orders] AS [o2]
WHERE [t1].[row] <= 1
) AS [t0] ON [t].[OrderID] = [t0].[OrderID]
LEFT JOIN [Order Details] AS [o3] ON [t0].[OrderID] = [o3].[OrderID]
-ORDER BY [t].[OrderID], [t0].[OrderID], [o3].[OrderID]");
+ORDER BY [t].[OrderID], [t0].[OrderID0], [t0].[ProductID], [t0].[OrderID], [o3].[OrderID]");
}
public override async Task SelectMany_Include_reference_GroupBy_Select(bool async)
diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindSplitIncludeQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindSplitIncludeQuerySqlServerTest.cs
index 15f238a0fc6..7cb18e992ff 100644
--- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindSplitIncludeQuerySqlServerTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindSplitIncludeQuerySqlServerTest.cs
@@ -1477,7 +1477,7 @@ public override async Task Include_collection_Join_GroupBy_Select(bool async)
await base.Include_collection_Join_GroupBy_Select(async);
AssertSql(
- @"SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t].[OrderID]
+ @"SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t].[OrderID], [t0].[OrderID0], [t0].[ProductID]
FROM (
SELECT [o].[OrderID]
FROM [Orders] AS [o]
@@ -1486,18 +1486,18 @@ FROM [Orders] AS [o]
GROUP BY [o].[OrderID]
) AS [t]
LEFT JOIN (
- SELECT [t1].[OrderID], [t1].[CustomerID], [t1].[EmployeeID], [t1].[OrderDate]
+ SELECT [t1].[OrderID], [t1].[CustomerID], [t1].[EmployeeID], [t1].[OrderDate], [t1].[OrderID0], [t1].[ProductID]
FROM (
- SELECT [o1].[OrderID], [o1].[CustomerID], [o1].[EmployeeID], [o1].[OrderDate], ROW_NUMBER() OVER(PARTITION BY [o1].[OrderID] ORDER BY [o1].[OrderID]) AS [row]
+ SELECT [o1].[OrderID], [o1].[CustomerID], [o1].[EmployeeID], [o1].[OrderDate], [o2].[OrderID] AS [OrderID0], [o2].[ProductID], ROW_NUMBER() OVER(PARTITION BY [o1].[OrderID] ORDER BY [o1].[OrderID]) AS [row]
FROM [Orders] AS [o1]
INNER JOIN [Order Details] AS [o2] ON [o1].[OrderID] = [o2].[OrderID]
WHERE [o1].[OrderID] = 10248
) AS [t1]
WHERE [t1].[row] <= 1
) AS [t0] ON [t].[OrderID] = [t0].[OrderID]
-ORDER BY [t].[OrderID], [t0].[OrderID]",
+ORDER BY [t].[OrderID], [t0].[OrderID], [t0].[OrderID0], [t0].[ProductID]",
//
- @"SELECT [o3].[OrderID], [o3].[ProductID], [o3].[Discount], [o3].[Quantity], [o3].[UnitPrice], [t].[OrderID], [t0].[OrderID]
+ @"SELECT [o3].[OrderID], [o3].[ProductID], [o3].[Discount], [o3].[Quantity], [o3].[UnitPrice], [t].[OrderID], [t0].[OrderID], [t0].[OrderID0], [t0].[ProductID]
FROM (
SELECT [o].[OrderID]
FROM [Orders] AS [o]
@@ -1506,9 +1506,9 @@ FROM [Orders] AS [o]
GROUP BY [o].[OrderID]
) AS [t]
LEFT JOIN (
- SELECT [t1].[OrderID]
+ SELECT [t1].[OrderID], [t1].[OrderID0], [t1].[ProductID]
FROM (
- SELECT [o1].[OrderID], ROW_NUMBER() OVER(PARTITION BY [o1].[OrderID] ORDER BY [o1].[OrderID]) AS [row]
+ SELECT [o1].[OrderID], [o2].[OrderID] AS [OrderID0], [o2].[ProductID], ROW_NUMBER() OVER(PARTITION BY [o1].[OrderID] ORDER BY [o1].[OrderID]) AS [row]
FROM [Orders] AS [o1]
INNER JOIN [Order Details] AS [o2] ON [o1].[OrderID] = [o2].[OrderID]
WHERE [o1].[OrderID] = 10248
@@ -1516,7 +1516,7 @@ FROM [Orders] AS [o1]
WHERE [t1].[row] <= 1
) AS [t0] ON [t].[OrderID] = [t0].[OrderID]
INNER JOIN [Order Details] AS [o3] ON [t0].[OrderID] = [o3].[OrderID]
-ORDER BY [t].[OrderID], [t0].[OrderID]");
+ORDER BY [t].[OrderID], [t0].[OrderID], [t0].[OrderID0], [t0].[ProductID]");
}
public override async Task Include_reference_Join_GroupBy_Select(bool async)
@@ -1550,7 +1550,7 @@ public override async Task Join_Include_collection_GroupBy_Select(bool async)
await base.Join_Include_collection_GroupBy_Select(async);
AssertSql(
- @"SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t].[OrderID]
+ @"SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t].[OrderID], [t0].[OrderID0], [t0].[ProductID]
FROM (
SELECT [o0].[OrderID]
FROM [Order Details] AS [o]
@@ -1559,18 +1559,18 @@ FROM [Order Details] AS [o]
GROUP BY [o0].[OrderID]
) AS [t]
LEFT JOIN (
- SELECT [t1].[OrderID], [t1].[CustomerID], [t1].[EmployeeID], [t1].[OrderDate]
+ SELECT [t1].[OrderID], [t1].[CustomerID], [t1].[EmployeeID], [t1].[OrderDate], [t1].[OrderID0], [t1].[ProductID]
FROM (
- SELECT [o2].[OrderID], [o2].[CustomerID], [o2].[EmployeeID], [o2].[OrderDate], ROW_NUMBER() OVER(PARTITION BY [o2].[OrderID] ORDER BY [o2].[OrderID]) AS [row]
+ SELECT [o2].[OrderID], [o2].[CustomerID], [o2].[EmployeeID], [o2].[OrderDate], [o1].[OrderID] AS [OrderID0], [o1].[ProductID], ROW_NUMBER() OVER(PARTITION BY [o2].[OrderID] ORDER BY [o2].[OrderID]) AS [row]
FROM [Order Details] AS [o1]
INNER JOIN [Orders] AS [o2] ON [o1].[OrderID] = [o2].[OrderID]
WHERE [o1].[OrderID] = 10248
) AS [t1]
WHERE [t1].[row] <= 1
) AS [t0] ON [t].[OrderID] = [t0].[OrderID]
-ORDER BY [t].[OrderID], [t0].[OrderID]",
+ORDER BY [t].[OrderID], [t0].[OrderID0], [t0].[ProductID], [t0].[OrderID]",
//
- @"SELECT [o3].[OrderID], [o3].[ProductID], [o3].[Discount], [o3].[Quantity], [o3].[UnitPrice], [t].[OrderID], [t0].[OrderID]
+ @"SELECT [o3].[OrderID], [o3].[ProductID], [o3].[Discount], [o3].[Quantity], [o3].[UnitPrice], [t].[OrderID], [t0].[OrderID0], [t0].[ProductID], [t0].[OrderID]
FROM (
SELECT [o0].[OrderID]
FROM [Order Details] AS [o]
@@ -1579,9 +1579,9 @@ FROM [Order Details] AS [o]
GROUP BY [o0].[OrderID]
) AS [t]
LEFT JOIN (
- SELECT [t1].[OrderID]
+ SELECT [t1].[OrderID], [t1].[OrderID0], [t1].[ProductID]
FROM (
- SELECT [o2].[OrderID], ROW_NUMBER() OVER(PARTITION BY [o2].[OrderID] ORDER BY [o2].[OrderID]) AS [row]
+ SELECT [o2].[OrderID], [o1].[OrderID] AS [OrderID0], [o1].[ProductID], ROW_NUMBER() OVER(PARTITION BY [o2].[OrderID] ORDER BY [o2].[OrderID]) AS [row]
FROM [Order Details] AS [o1]
INNER JOIN [Orders] AS [o2] ON [o1].[OrderID] = [o2].[OrderID]
WHERE [o1].[OrderID] = 10248
@@ -1589,7 +1589,7 @@ FROM [Order Details] AS [o1]
WHERE [t1].[row] <= 1
) AS [t0] ON [t].[OrderID] = [t0].[OrderID]
INNER JOIN [Order Details] AS [o3] ON [t0].[OrderID] = [o3].[OrderID]
-ORDER BY [t].[OrderID], [t0].[OrderID]");
+ORDER BY [t].[OrderID], [t0].[OrderID0], [t0].[ProductID], [t0].[OrderID]");
}
public override async Task Join_Include_reference_GroupBy_Select(bool async)
@@ -1621,7 +1621,7 @@ public override async Task Include_collection_SelectMany_GroupBy_Select(bool asy
await base.Include_collection_SelectMany_GroupBy_Select(async);
AssertSql(
- @"SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t].[OrderID]
+ @"SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t].[OrderID], [t0].[OrderID0], [t0].[ProductID]
FROM (
SELECT [o].[OrderID]
FROM [Orders] AS [o]
@@ -1630,18 +1630,18 @@ CROSS JOIN [Order Details] AS [o0]
GROUP BY [o].[OrderID]
) AS [t]
LEFT JOIN (
- SELECT [t1].[OrderID], [t1].[CustomerID], [t1].[EmployeeID], [t1].[OrderDate]
+ SELECT [t1].[OrderID], [t1].[CustomerID], [t1].[EmployeeID], [t1].[OrderDate], [t1].[OrderID0], [t1].[ProductID]
FROM (
- SELECT [o1].[OrderID], [o1].[CustomerID], [o1].[EmployeeID], [o1].[OrderDate], ROW_NUMBER() OVER(PARTITION BY [o1].[OrderID] ORDER BY [o1].[OrderID]) AS [row]
+ SELECT [o1].[OrderID], [o1].[CustomerID], [o1].[EmployeeID], [o1].[OrderDate], [o2].[OrderID] AS [OrderID0], [o2].[ProductID], ROW_NUMBER() OVER(PARTITION BY [o1].[OrderID] ORDER BY [o1].[OrderID]) AS [row]
FROM [Orders] AS [o1]
CROSS JOIN [Order Details] AS [o2]
WHERE [o1].[OrderID] = 10248
) AS [t1]
WHERE [t1].[row] <= 1
) AS [t0] ON [t].[OrderID] = [t0].[OrderID]
-ORDER BY [t].[OrderID], [t0].[OrderID]",
+ORDER BY [t].[OrderID], [t0].[OrderID], [t0].[OrderID0], [t0].[ProductID]",
//
- @"SELECT [o3].[OrderID], [o3].[ProductID], [o3].[Discount], [o3].[Quantity], [o3].[UnitPrice], [t].[OrderID], [t0].[OrderID]
+ @"SELECT [o3].[OrderID], [o3].[ProductID], [o3].[Discount], [o3].[Quantity], [o3].[UnitPrice], [t].[OrderID], [t0].[OrderID], [t0].[OrderID0], [t0].[ProductID]
FROM (
SELECT [o].[OrderID]
FROM [Orders] AS [o]
@@ -1650,9 +1650,9 @@ CROSS JOIN [Order Details] AS [o0]
GROUP BY [o].[OrderID]
) AS [t]
LEFT JOIN (
- SELECT [t1].[OrderID]
+ SELECT [t1].[OrderID], [t1].[OrderID0], [t1].[ProductID]
FROM (
- SELECT [o1].[OrderID], ROW_NUMBER() OVER(PARTITION BY [o1].[OrderID] ORDER BY [o1].[OrderID]) AS [row]
+ SELECT [o1].[OrderID], [o2].[OrderID] AS [OrderID0], [o2].[ProductID], ROW_NUMBER() OVER(PARTITION BY [o1].[OrderID] ORDER BY [o1].[OrderID]) AS [row]
FROM [Orders] AS [o1]
CROSS JOIN [Order Details] AS [o2]
WHERE [o1].[OrderID] = 10248
@@ -1660,7 +1660,7 @@ CROSS JOIN [Order Details] AS [o2]
WHERE [t1].[row] <= 1
) AS [t0] ON [t].[OrderID] = [t0].[OrderID]
INNER JOIN [Order Details] AS [o3] ON [t0].[OrderID] = [o3].[OrderID]
-ORDER BY [t].[OrderID], [t0].[OrderID]");
+ORDER BY [t].[OrderID], [t0].[OrderID], [t0].[OrderID0], [t0].[ProductID]");
}
public override async Task Include_reference_SelectMany_GroupBy_Select(bool async)
@@ -1694,7 +1694,7 @@ public override async Task SelectMany_Include_collection_GroupBy_Select(bool asy
await base.SelectMany_Include_collection_GroupBy_Select(async);
AssertSql(
- @"SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t].[OrderID]
+ @"SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t].[OrderID], [t0].[OrderID0], [t0].[ProductID]
FROM (
SELECT [o0].[OrderID]
FROM [Order Details] AS [o]
@@ -1703,18 +1703,18 @@ CROSS JOIN [Orders] AS [o0]
GROUP BY [o0].[OrderID]
) AS [t]
LEFT JOIN (
- SELECT [t1].[OrderID], [t1].[CustomerID], [t1].[EmployeeID], [t1].[OrderDate]
+ SELECT [t1].[OrderID], [t1].[CustomerID], [t1].[EmployeeID], [t1].[OrderDate], [t1].[OrderID0], [t1].[ProductID]
FROM (
- SELECT [o2].[OrderID], [o2].[CustomerID], [o2].[EmployeeID], [o2].[OrderDate], ROW_NUMBER() OVER(PARTITION BY [o2].[OrderID] ORDER BY [o2].[OrderID]) AS [row]
+ SELECT [o2].[OrderID], [o2].[CustomerID], [o2].[EmployeeID], [o2].[OrderDate], [o1].[OrderID] AS [OrderID0], [o1].[ProductID], ROW_NUMBER() OVER(PARTITION BY [o2].[OrderID] ORDER BY [o2].[OrderID]) AS [row]
FROM [Order Details] AS [o1]
CROSS JOIN [Orders] AS [o2]
WHERE [o1].[OrderID] = 10248
) AS [t1]
WHERE [t1].[row] <= 1
) AS [t0] ON [t].[OrderID] = [t0].[OrderID]
-ORDER BY [t].[OrderID], [t0].[OrderID]",
+ORDER BY [t].[OrderID], [t0].[OrderID0], [t0].[ProductID], [t0].[OrderID]",
//
- @"SELECT [o3].[OrderID], [o3].[ProductID], [o3].[Discount], [o3].[Quantity], [o3].[UnitPrice], [t].[OrderID], [t0].[OrderID]
+ @"SELECT [o3].[OrderID], [o3].[ProductID], [o3].[Discount], [o3].[Quantity], [o3].[UnitPrice], [t].[OrderID], [t0].[OrderID0], [t0].[ProductID], [t0].[OrderID]
FROM (
SELECT [o0].[OrderID]
FROM [Order Details] AS [o]
@@ -1723,9 +1723,9 @@ CROSS JOIN [Orders] AS [o0]
GROUP BY [o0].[OrderID]
) AS [t]
LEFT JOIN (
- SELECT [t1].[OrderID]
+ SELECT [t1].[OrderID], [t1].[OrderID0], [t1].[ProductID]
FROM (
- SELECT [o2].[OrderID], ROW_NUMBER() OVER(PARTITION BY [o2].[OrderID] ORDER BY [o2].[OrderID]) AS [row]
+ SELECT [o2].[OrderID], [o1].[OrderID] AS [OrderID0], [o1].[ProductID], ROW_NUMBER() OVER(PARTITION BY [o2].[OrderID] ORDER BY [o2].[OrderID]) AS [row]
FROM [Order Details] AS [o1]
CROSS JOIN [Orders] AS [o2]
WHERE [o1].[OrderID] = 10248
@@ -1733,7 +1733,7 @@ CROSS JOIN [Orders] AS [o2]
WHERE [t1].[row] <= 1
) AS [t0] ON [t].[OrderID] = [t0].[OrderID]
INNER JOIN [Order Details] AS [o3] ON [t0].[OrderID] = [o3].[OrderID]
-ORDER BY [t].[OrderID], [t0].[OrderID]");
+ORDER BY [t].[OrderID], [t0].[OrderID0], [t0].[ProductID], [t0].[OrderID]");
}
public override async Task SelectMany_Include_reference_GroupBy_Select(bool async)
diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs
index 14dcaaf851e..10058b6924e 100644
--- a/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs
@@ -6539,7 +6539,7 @@ LEFT JOIN (
FROM (
SELECT [g0].[Nickname], [g0].[SquadId], [g0].[AssignedCityName], [g0].[CityOfBirthName], [g0].[FullName], [g0].[HasSoulPatch], [g0].[LeaderNickname], [g0].[LeaderSquadId], [g0].[Rank], CASE
WHEN [o0].[Nickname] IS NOT NULL THEN N'Officer'
- END AS [Discriminator], [c].[Name], [c].[Location], [c].[Nation], ROW_NUMBER() OVER(PARTITION BY [g0].[Rank] ORDER BY [g0].[Rank], [c].[Name]) AS [row]
+ END AS [Discriminator], [c].[Name], [c].[Location], [c].[Nation], ROW_NUMBER() OVER(PARTITION BY [g0].[Rank] ORDER BY [g0].[Nickname], [g0].[SquadId], [c].[Name]) AS [row]
FROM [Gears] AS [g0]
LEFT JOIN [Officers] AS [o0] ON ([g0].[Nickname] = [o0].[Nickname]) AND ([g0].[SquadId] = [o0].[SquadId])
INNER JOIN [Cities] AS [c] ON [g0].[CityOfBirthName] = [c].[Name]