diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs b/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs index 31b864eb51f..9c1692c45e6 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs @@ -870,6 +870,22 @@ private static Expression GetGroupingKey(Expression key, List groupi return memberInitExpression.Update(updatedNewExpression, memberBindings); + case EntityShaperExpression entityShaperExpression + when entityShaperExpression.ValueBufferExpression is ProjectionBindingExpression projectionBindingExpression: + var entityProjectionExpression = (EntityProjectionExpression)((InMemoryQueryExpression)projectionBindingExpression.QueryExpression) + .GetProjection(projectionBindingExpression); + var readExpressions = new Dictionary(); + foreach (var property in GetAllPropertiesInHierarchy(entityProjectionExpression.EntityType)) + { + readExpressions[property] = (MethodCallExpression)GetGroupingKey( + entityProjectionExpression.BindProperty(property), + groupingExpressions, + groupingKeyAccessExpression); + } + + return entityShaperExpression.Update( + new EntityProjectionExpression(entityProjectionExpression.EntityType, readExpressions)); + default: var index = groupingExpressions.Count; groupingExpressions.Add(key); diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs index 5f9ff6cba25..ec5e2ebdbb8 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs @@ -455,6 +455,10 @@ private static ShapedQueryExpression CreateShapedQueryExpressionStatic(IEntityTy return memberInitExpression.Update(updatedNewExpression, newBindings); + case EntityShaperExpression entityShaperExpression + when entityShaperExpression.ValueBufferExpression is ProjectionBindingExpression projectionBindingExpression: + return entityShaperExpression; + default: var translation = TranslateExpression(expression); if (translation == null) diff --git a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs index 7809084f24e..f19ad57d426 100644 --- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs @@ -450,7 +450,16 @@ private static ShapedQueryExpression CreateShapedQueryExpression(IEntityType ent var translatedKey = TranslateGroupingKey(remappedKeySelector); if (translatedKey == null) { - return null; + // This could be group by entity type + if (remappedKeySelector is not EntityShaperExpression + { ValueBufferExpression : ProjectionBindingExpression }) + { + // ValueBufferExpression can be JsonQuery, ProjectionBindingExpression, EntityProjection + // We only allow ProjectionBindingExpression which represents a regular entity + return null; + } + + translatedKey = remappedKeySelector; } if (elementSelector != null) diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs index 174e54dfc6c..b5136d777c2 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs @@ -1857,6 +1857,23 @@ private static void PopulateGroupByTerms( PopulateGroupByTerms(unaryExpression.Operand, groupByTerms, groupByAliases, name); break; + case EntityShaperExpression entityShaperExpression + when entityShaperExpression.ValueBufferExpression is ProjectionBindingExpression projectionBindingExpression: + var entityProjectionExpression = (EntityProjectionExpression)((SelectExpression)projectionBindingExpression.QueryExpression) + .GetProjection(projectionBindingExpression); + foreach (var property in GetAllPropertiesInHierarchy(entityProjectionExpression.EntityType)) + { + PopulateGroupByTerms(entityProjectionExpression.BindProperty(property), groupByTerms, groupByAliases, name: null); + } + + if (entityProjectionExpression.DiscriminatorExpression != null) + { + PopulateGroupByTerms( + entityProjectionExpression.DiscriminatorExpression, groupByTerms, groupByAliases, name: DiscriminatorColumnAlias); + } + + break; + default: throw new InvalidOperationException(RelationalStrings.InvalidKeySelectorForGroupBy(keySelector, keySelector.GetType())); } diff --git a/test/EFCore.Specification.Tests/Query/Ef6GroupByTestBase.cs b/test/EFCore.Specification.Tests/Query/Ef6GroupByTestBase.cs index f859f622a15..08494e5e0ae 100644 --- a/test/EFCore.Specification.Tests/Query/Ef6GroupByTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/Ef6GroupByTestBase.cs @@ -109,11 +109,18 @@ public virtual Task GroupBy_is_optimized_when_grouping_by_row_and_projecting_col [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Grouping_by_all_columns_doesnt_produce_a_groupby_statement(bool async) - // GroupBy entityType. Issue #17653. - => AssertTranslationFailed( - () => AssertQuery( - async, - ss => ss.Set().GroupBy(o => o).Select(g => g.Key))); + => AssertQuery( + async, + ss => ss.Set().GroupBy(o => o).Select(g => g.Key), + elementSorter: e => e.Id, + elementAsserter: (e, a) => + { + Assert.Equal(e.Id, a.Id); + Assert.Equal(e.Alias, a.Alias); + Assert.Equal(e.FirstName, a.FirstName); + Assert.Equal(e.LastName, a.LastName); + }, + entryCount: 10); [ConditionalTheory] [MemberData(nameof(IsAsyncData))] @@ -132,111 +139,93 @@ public virtual Task Grouping_by_all_columns_with_aggregate_function_works_1(bool [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Grouping_by_all_columns_with_aggregate_function_works_2(bool async) - // GroupBy entityType. Issue #17653. - => AssertTranslationFailed( - () => AssertQueryScalar( - async, - ss => ss.Set().GroupBy(o => o, c => new { c.LastName, c.FirstName }, (k, g) => g.Count()))); + => AssertQueryScalar( + async, + ss => ss.Set().GroupBy(o => o, c => new { c.LastName, c.FirstName }, (k, g) => g.Count())); [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Grouping_by_all_columns_with_aggregate_function_works_3(bool async) - // GroupBy entityType. Issue #17653. - => AssertTranslationFailed( - () => AssertQueryScalar( - async, - ss => ss.Set().GroupBy(o => o, c => c, (k, g) => g.Count()))); + => AssertQueryScalar( + async, + ss => ss.Set().GroupBy(o => o, c => c, (k, g) => g.Count())); [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Grouping_by_all_columns_with_aggregate_function_works_4(bool async) - // GroupBy entityType. Issue #17653. - => AssertTranslationFailed( - () => AssertQuery( - async, - ss => ss.Set().GroupBy(o => o, c => c, (k, g) => new { Count = g.Count() }))); + => AssertQuery( + async, + ss => ss.Set().GroupBy(o => o, c => c, (k, g) => new { Count = g.Count() })); [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Grouping_by_all_columns_with_aggregate_function_works_5(bool async) - // GroupBy entityType. Issue #17653. - => AssertTranslationFailed( - () => AssertQuery( - async, - ss => ss.Set().GroupBy(o => o, c => c, (k, g) => new { k.Id, Count = g.Count() }))); + => AssertQuery( + async, + ss => ss.Set().GroupBy(o => o, c => c, (k, g) => new { k.Id, Count = g.Count() })); [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Grouping_by_all_columns_with_aggregate_function_works_6(bool async) - // GroupBy entityType. Issue #17653. - => AssertTranslationFailed( - () => AssertQuery( - async, - ss => ss.Set().GroupBy( - o => o, c => c, (k, g) => new - { - k.Id, - k.Alias, - Count = g.Count() - }))); + => AssertQuery( + async, + ss => ss.Set().GroupBy( + o => o, c => c, (k, g) => new + { + k.Id, + k.Alias, + Count = g.Count() + })); [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Grouping_by_all_columns_with_aggregate_function_works_7(bool async) - // GroupBy entityType. Issue #17653. - => AssertTranslationFailed( - () => AssertQueryScalar( - async, - ss => from o in ss.Set() - group o by o - into g - select g.Count())); + => AssertQueryScalar( + async, + ss => from o in ss.Set() + group o by o + into g + select g.Count()); [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Grouping_by_all_columns_with_aggregate_function_works_8(bool async) - // GroupBy entityType. Issue #17653. - => AssertTranslationFailed( - () => AssertQuery( - async, - ss => from o in ss.Set() - group o by o - into g - select new { g.Key.Id, Count = g.Count() })); + => AssertQuery( + async, + ss => from o in ss.Set() + group o by o + into g + select new { g.Key.Id, Count = g.Count() }); [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Grouping_by_all_columns_with_aggregate_function_works_9(bool async) - // GroupBy entityType. Issue #17653. - => AssertTranslationFailed( - () => AssertQuery( - async, - ss => from o in ss.Set() - group o by o - into g - select new - { - g.Key.Id, - g.Key.Alias, - Count = g.Count() - })); + => AssertQuery( + async, + ss => from o in ss.Set() + group o by o + into g + select new + { + g.Key.Id, + g.Key.Alias, + Count = g.Count() + }); [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Grouping_by_all_columns_with_aggregate_function_works_10(bool async) - // GroupBy entityType. Issue #17653. - => AssertTranslationFailed( - () => AssertQuery( - async, - ss => from o in ss.Set() - group o by o - into g - select new - { - g.Key.Id, - Sum = g.Sum(x => x.Id), - Count = g.Count() - })); + => AssertQuery( + async, + ss => from o in ss.Set() + group o by o + into g + select new + { + g.Key.Id, + Sum = g.Sum(x => x.Id), + Count = g.Count() + }); [ConditionalTheory] [MemberData(nameof(IsAsyncData))] @@ -731,7 +720,6 @@ public virtual Task Whats_new_2021_sample_13(bool async) [ConditionalTheory] // From #12088 [MemberData(nameof(IsAsyncData))] public virtual Task Whats_new_2021_sample_14(bool async) - // GroupBy entityType. Issue #17653. => AssertTranslationFailed( () => AssertQuery( async, @@ -742,13 +730,12 @@ public virtual Task Whats_new_2021_sample_14(bool async) [ConditionalTheory] // From #12088 [MemberData(nameof(IsAsyncData))] public virtual Task Whats_new_2021_sample_15(bool async) - // GroupBy entityType. Issue #17653. - => AssertTranslationFailed( - () => AssertQuery( - async, - ss => ss.Set() - .GroupBy(bp => bp.Feet) - .Select(g => g.OrderByDescending(bp => bp.Id).FirstOrDefault()))); + => AssertQuery( + async, + ss => ss.Set() + .GroupBy(bp => bp.Feet) + .Select(g => g.OrderByDescending(bp => bp.Id).FirstOrDefault()), + entryCount: 12); [ConditionalTheory] // From #12573 [MemberData(nameof(IsAsyncData))] diff --git a/test/EFCore.Specification.Tests/Query/NorthwindGroupByQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/NorthwindGroupByQueryTestBase.cs index 965477edae0..072bcaca56f 100644 --- a/test/EFCore.Specification.Tests/Query/NorthwindGroupByQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/NorthwindGroupByQueryTestBase.cs @@ -2688,6 +2688,19 @@ public virtual Task GroupBy_selecting_grouping_key_list(bool async) AssertCollection(e.Data, a.Data); }); + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Select_GroupBy_SelectMany(bool async) + // Entity equality. Issue #15938. + => AssertTranslationFailed( + () => AssertQuery( + async, + ss => ss.Set().Select( + o => new ProjectedType { Order = o.OrderID, Customer = o.CustomerID }) + .GroupBy(p => p.Customer) + .SelectMany(g => g), + elementSorter: g => g.Order)); + #endregion #region GroupBySelectFirst @@ -2788,81 +2801,73 @@ public virtual Task GroupBy_select_grouping_composed_list_2(bool async) #region GroupByEntityType - [ConditionalTheory] - [MemberData(nameof(IsAsyncData))] - public virtual Task Select_GroupBy_SelectMany(bool async) - // Entity equality. Issue #15938. - => AssertTranslationFailed( - () => AssertQuery( - async, - ss => ss.Set().Select( - o => new ProjectedType { Order = o.OrderID, Customer = o.CustomerID }) - .GroupBy(p => p.Customer) - .SelectMany(g => g), - elementSorter: g => g.Order)); - [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task GroupBy_with_group_key_being_navigation(bool async) - // Entity equality. Issue #15938. - => AssertTranslationFailed( - () => AssertQuery( - async, - ss => ss.Set() - .GroupBy(od => od.Order) - .Select(g => new { g.Key, Aggregate = g.Sum(od => od.OrderID) }), - elementSorter: e => e.Key)); + => AssertQuery( + async, + ss => ss.Set() + .GroupBy(od => od.Order) + .Select(g => new { g.Key, Aggregate = g.Sum(od => od.OrderID) }), + elementSorter: e => e.Key.OrderID, + elementAsserter: (e, a) => + { + AssertEqual(e.Key, a.Key); + AssertEqual(e.Aggregate, a.Aggregate); + }, + entryCount: 830); [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task GroupBy_with_group_key_being_nested_navigation(bool async) - // Entity equality. Issue #15938. - => AssertTranslationFailed( - () => AssertQuery( - async, - ss => ss.Set() - .GroupBy(od => od.Order.Customer) - .Select(g => new { g.Key, Aggregate = g.Sum(od => od.OrderID) }), - elementSorter: e => e.Key)); + => AssertQuery( + async, + ss => ss.Set() + .GroupBy(od => od.Order.Customer) + .Select(g => new { g.Key, Aggregate = g.Sum(od => od.OrderID) }), + elementSorter: e => e.Key.CustomerID, + elementAsserter: (e, a) => + { + AssertEqual(e.Key, a.Key); + AssertEqual(e.Aggregate, a.Aggregate); + }, + entryCount: 89); [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task GroupBy_with_group_key_being_navigation_with_entity_key_projection(bool async) - // Entity equality. Issue #15938. - => AssertTranslationFailed( - () => AssertQuery( - async, - ss => ss.Set() - .GroupBy(od => od.Order) - .Select(g => g.Key))); + => AssertQuery( + async, + ss => ss.Set() + .GroupBy(od => od.Order) + .Select(g => g.Key), + entryCount: 830); - [ConditionalTheory] + [ConditionalTheory(Skip = "Issue#29014")] [MemberData(nameof(IsAsyncData))] public virtual Task GroupBy_with_group_key_being_navigation_with_complex_projection(bool async) - // Entity equality. Issue #15938. - => AssertTranslationFailed( - () => AssertQuery( - async, - ss => ss.Set() - .GroupBy(od => od.Order) - .Select( - g => new - { - g.Key, - Id1 = g.Key.CustomerID, - Id2 = g.Key.Customer.CustomerID, - Id3 = g.Key.OrderID, - Aggregate = g.Sum(od => od.OrderID) - }), - elementSorter: e => e.Id3, - elementAsserter: (e, a) => - { - AssertEqual(e.Key, a.Key); - Assert.Equal(e.Id1, a.Id1); - Assert.Equal(e.Id2, a.Id2); - Assert.Equal(e.Id3, a.Id3); - Assert.Equal(e.Aggregate, a.Aggregate); - })); + => AssertQuery( + async, + ss => ss.Set() + .GroupBy(od => od.Order) + .Select( + g => new + { + g.Key, + Id1 = g.Key.CustomerID, + Id2 = g.Key.Customer.CustomerID, + Id3 = g.Key.OrderID, + Aggregate = g.Sum(od => od.OrderID) + }), + elementSorter: e => e.Id3, + elementAsserter: (e, a) => + { + AssertEqual(e.Key, a.Key); + Assert.Equal(e.Id1, a.Id1); + Assert.Equal(e.Id2, a.Id2); + Assert.Equal(e.Id3, a.Id3); + Assert.Equal(e.Aggregate, a.Aggregate); + }); #endregion diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/Ef6GroupBySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/Ef6GroupBySqlServerTest.cs index 8418b4d3370..f6d3becd521 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/Ef6GroupBySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/Ef6GroupBySqlServerTest.cs @@ -261,15 +261,10 @@ public override async Task Grouping_by_all_columns_doesnt_produce_a_groupby_stat { await base.Grouping_by_all_columns_doesnt_produce_a_groupby_statement(async); - AssertSql(); - - // EF6 SQL: - // @"SELECT - // [Extent1].[Id] AS [Id], - // [Extent1].[FirstName] AS [FirstName], - // [Extent1].[LastName] AS [LastName], - // [Extent1].[Alias] AS [Alias] - // FROM [dbo].[ArubaOwners] AS [Extent1]"; + AssertSql( + @"SELECT [a].[Id], [a].[Alias], [a].[FirstName], [a].[LastName] +FROM [ArubaOwner] AS [a] +GROUP BY [a].[Id], [a].[Alias], [a].[FirstName], [a].[LastName]"); } public override async Task Grouping_by_all_columns_with_aggregate_function_works_1(bool async) @@ -294,175 +289,90 @@ public override async Task Grouping_by_all_columns_with_aggregate_function_works { await base.Grouping_by_all_columns_with_aggregate_function_works_2(async); - AssertSql(); - - // EF6 SQL: - // @"SELECT - // (SELECT - // COUNT(1) AS [A1] - // FROM [dbo].[ArubaOwners] AS [Extent2] - // WHERE [Extent1].[Id] = [Extent2].[Id]) AS [C1] - // FROM [dbo].[ArubaOwners] AS [Extent1]"; + AssertSql( + @"SELECT COUNT(*) +FROM [ArubaOwner] AS [a] +GROUP BY [a].[Id], [a].[Alias], [a].[FirstName], [a].[LastName]"); } public override async Task Grouping_by_all_columns_with_aggregate_function_works_3(bool async) { await base.Grouping_by_all_columns_with_aggregate_function_works_3(async); - AssertSql(); - - // EF6 SQL: - // @"SELECT - // (SELECT - // COUNT(1) AS [A1] - // FROM [dbo].[ArubaOwners] AS [Extent2] - // WHERE [Extent1].[Id] = [Extent2].[Id]) AS [C1] - // FROM [dbo].[ArubaOwners] AS [Extent1]"; + AssertSql( + @"SELECT COUNT(*) +FROM [ArubaOwner] AS [a] +GROUP BY [a].[Id], [a].[Alias], [a].[FirstName], [a].[LastName]"); } public override async Task Grouping_by_all_columns_with_aggregate_function_works_4(bool async) { await base.Grouping_by_all_columns_with_aggregate_function_works_4(async); - AssertSql(); - - // EF6 SQL: - // @"SELECT - // [GroupBy1].[K1] AS [Id], - // [GroupBy1].[A1] AS [C1] - // FROM ( SELECT - // [Extent1].[Id] AS [K1], - // [Extent1].[FirstName] AS [K2], - // [Extent1].[LastName] AS [K3], - // [Extent1].[Alias] AS [K4], - // COUNT(1) AS [A1] - // FROM [dbo].[ArubaOwners] AS [Extent1] - // GROUP BY [Extent1].[Id], [Extent1].[FirstName], [Extent1].[LastName], [Extent1].[Alias] - // ) AS [GroupBy1]"; + AssertSql( + @"SELECT COUNT(*) AS [Count] +FROM [ArubaOwner] AS [a] +GROUP BY [a].[Id], [a].[Alias], [a].[FirstName], [a].[LastName]"); } public override async Task Grouping_by_all_columns_with_aggregate_function_works_5(bool async) { await base.Grouping_by_all_columns_with_aggregate_function_works_5(async); - AssertSql(); - - // EF6 SQL: - // @"SELECT - // [GroupBy1].[K1] AS [Id], - // [GroupBy1].[A1] AS [C1] - // FROM ( SELECT - // [Extent1].[Id] AS [K1], - // [Extent1].[FirstName] AS [K2], - // [Extent1].[LastName] AS [K3], - // [Extent1].[Alias] AS [K4], - // COUNT(1) AS [A1] - // FROM [dbo].[ArubaOwners] AS [Extent1] - // GROUP BY [Extent1].[Id], [Extent1].[FirstName], [Extent1].[LastName], [Extent1].[Alias] - // ) AS [GroupBy1]"; + AssertSql( + @"SELECT [a].[Id], COUNT(*) AS [Count] +FROM [ArubaOwner] AS [a] +GROUP BY [a].[Id], [a].[Alias], [a].[FirstName], [a].[LastName]"); } public override async Task Grouping_by_all_columns_with_aggregate_function_works_6(bool async) { await base.Grouping_by_all_columns_with_aggregate_function_works_6(async); - AssertSql(); - - // EF6 SQL: - // @"SELECT - // [GroupBy1].[K1] AS [Id], - // [GroupBy1].[K4] AS [Alias], - // [GroupBy1].[A1] AS [C1] - // FROM ( SELECT - // [Extent1].[Id] AS [K1], - // [Extent1].[FirstName] AS [K2], - // [Extent1].[LastName] AS [K3], - // [Extent1].[Alias] AS [K4], - // COUNT(1) AS [A1] - // FROM [dbo].[ArubaOwners] AS [Extent1] - // GROUP BY [Extent1].[Id], [Extent1].[FirstName], [Extent1].[LastName], [Extent1].[Alias] - // ) AS [GroupBy1]"; + AssertSql( + @"SELECT [a].[Id], [a].[Alias], COUNT(*) AS [Count] +FROM [ArubaOwner] AS [a] +GROUP BY [a].[Id], [a].[Alias], [a].[FirstName], [a].[LastName]"); } public override async Task Grouping_by_all_columns_with_aggregate_function_works_7(bool async) { await base.Grouping_by_all_columns_with_aggregate_function_works_7(async); - AssertSql(); - - // EF6 SQL: - // @"SELECT - // (SELECT - // COUNT(1) AS [A1] - // FROM [dbo].[ArubaOwners] AS [Extent2] - // WHERE [Extent1].[Id] = [Extent2].[Id]) AS [C1] - // FROM [dbo].[ArubaOwners] AS [Extent1]"; + AssertSql( + @"SELECT COUNT(*) +FROM [ArubaOwner] AS [a] +GROUP BY [a].[Id], [a].[Alias], [a].[FirstName], [a].[LastName]"); } public override async Task Grouping_by_all_columns_with_aggregate_function_works_8(bool async) { await base.Grouping_by_all_columns_with_aggregate_function_works_8(async); - AssertSql(); - - // EF6 SQL: - // @"SELECT - // [GroupBy1].[K1] AS [Id], - // [GroupBy1].[A1] AS [C1] - // FROM ( SELECT - // [Extent1].[Id] AS [K1], - // [Extent1].[FirstName] AS [K2], - // [Extent1].[LastName] AS [K3], - // [Extent1].[Alias] AS [K4], - // COUNT(1) AS [A1] - // FROM [dbo].[ArubaOwners] AS [Extent1] - // GROUP BY [Extent1].[Id], [Extent1].[FirstName], [Extent1].[LastName], [Extent1].[Alias] - // ) AS [GroupBy1]"; + AssertSql( + @"SELECT [a].[Id], COUNT(*) AS [Count] +FROM [ArubaOwner] AS [a] +GROUP BY [a].[Id], [a].[Alias], [a].[FirstName], [a].[LastName]"); } public override async Task Grouping_by_all_columns_with_aggregate_function_works_9(bool async) { await base.Grouping_by_all_columns_with_aggregate_function_works_9(async); - AssertSql(); - - // EF6 SQL: - // @"SELECT - // [GroupBy1].[K1] AS [Id], - // [GroupBy1].[K4] AS [Alias], - // [GroupBy1].[A1] AS [C1] - // FROM ( SELECT - // [Extent1].[Id] AS [K1], - // [Extent1].[FirstName] AS [K2], - // [Extent1].[LastName] AS [K3], - // [Extent1].[Alias] AS [K4], - // COUNT(1) AS [A1] - // FROM [dbo].[ArubaOwners] AS [Extent1] - // GROUP BY [Extent1].[Id], [Extent1].[FirstName], [Extent1].[LastName], [Extent1].[Alias] - // ) AS [GroupBy1]"; + AssertSql( + @"SELECT [a].[Id], [a].[Alias], COUNT(*) AS [Count] +FROM [ArubaOwner] AS [a] +GROUP BY [a].[Id], [a].[Alias], [a].[FirstName], [a].[LastName]"); } public override async Task Grouping_by_all_columns_with_aggregate_function_works_10(bool async) { await base.Grouping_by_all_columns_with_aggregate_function_works_10(async); - AssertSql(); - - // EF6 SQL: - // @"SELECT - // [GroupBy1].[K1] AS [Id], - // [GroupBy1].[A1] AS [C1], - // [GroupBy1].[A2] AS [C2] - // FROM ( SELECT - // [Extent1].[Id] AS [K1], - // [Extent1].[FirstName] AS [K2], - // [Extent1].[LastName] AS [K3], - // [Extent1].[Alias] AS [K4], - // SUM([Extent1].[Id]) AS [A1], - // COUNT(1) AS [A2] - // FROM [dbo].[ArubaOwners] AS [Extent1] - // GROUP BY [Extent1].[Id], [Extent1].[FirstName], [Extent1].[LastName], [Extent1].[Alias] - // ) AS [GroupBy1]"; + AssertSql( + @"SELECT [a].[Id], COALESCE(SUM([a].[Id]), 0) AS [Sum], COUNT(*) AS [Count] +FROM [ArubaOwner] AS [a] +GROUP BY [a].[Id], [a].[Alias], [a].[FirstName], [a].[LastName]"); } public override async Task GroupBy_Simple_1_from_LINQ_101(bool async) @@ -622,7 +532,23 @@ public override async Task Whats_new_2021_sample_15(bool async) { await base.Whats_new_2021_sample_15(async); - AssertSql(); + AssertSql( + @"SELECT [t0].[Id], [t0].[Age], [t0].[FirstName], [t0].[LastName], [t0].[MiddleInitial] +FROM ( + SELECT [f].[Id], [f].[Size] + FROM [Person] AS [p] + LEFT JOIN [Feet] AS [f] ON [p].[Id] = [f].[Id] + GROUP BY [f].[Id], [f].[Size] +) AS [t] +LEFT JOIN ( + SELECT [t1].[Id], [t1].[Age], [t1].[FirstName], [t1].[LastName], [t1].[MiddleInitial], [t1].[Id0], [t1].[Size] + FROM ( + SELECT [p0].[Id], [p0].[Age], [p0].[FirstName], [p0].[LastName], [p0].[MiddleInitial], [f0].[Id] AS [Id0], [f0].[Size], ROW_NUMBER() OVER(PARTITION BY [f0].[Id], [f0].[Size] ORDER BY [p0].[Id] DESC) AS [row] + FROM [Person] AS [p0] + LEFT JOIN [Feet] AS [f0] ON [p0].[Id] = [f0].[Id] + ) AS [t1] + WHERE [t1].[row] <= 1 +) AS [t0] ON ([t].[Id] = [t0].[Id0] OR ([t].[Id] IS NULL AND [t0].[Id0] IS NULL)) AND ([t].[Size] = [t0].[Size] OR ([t].[Size] IS NULL AND [t0].[Size] IS NULL))"); } public override async Task Whats_new_2021_sample_16(bool async) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindGroupByQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindGroupByQuerySqlServerTest.cs index b38a1421882..bd45af8b62c 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindGroupByQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindGroupByQuerySqlServerTest.cs @@ -2464,21 +2464,34 @@ public override async Task GroupBy_with_group_key_being_navigation(bool async) { await base.GroupBy_with_group_key_being_navigation(async); - AssertSql(); + AssertSql( + @"SELECT [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate], COALESCE(SUM([o].[OrderID]), 0) AS [Aggregate] +FROM [Order Details] AS [o] +INNER JOIN [Orders] AS [o0] ON [o].[OrderID] = [o0].[OrderID] +GROUP BY [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate]"); } public override async Task GroupBy_with_group_key_being_nested_navigation(bool async) { await base.GroupBy_with_group_key_being_nested_navigation(async); - AssertSql(); + AssertSql( + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region], COALESCE(SUM([o].[OrderID]), 0) AS [Aggregate] +FROM [Order Details] AS [o] +INNER JOIN [Orders] AS [o0] ON [o].[OrderID] = [o0].[OrderID] +LEFT JOIN [Customers] AS [c] ON [o0].[CustomerID] = [c].[CustomerID] +GROUP BY [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region]"); } public override async Task GroupBy_with_group_key_being_navigation_with_entity_key_projection(bool async) { await base.GroupBy_with_group_key_being_navigation_with_entity_key_projection(async); - AssertSql(); + AssertSql( + @"SELECT [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate] +FROM [Order Details] AS [o] +INNER JOIN [Orders] AS [o0] ON [o].[OrderID] = [o0].[OrderID] +GROUP BY [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate]"); } public override async Task GroupBy_with_group_key_being_navigation_with_complex_projection(bool async)