From e0a1d68279cff3100512dbc8dcd3e813ef9938d9 Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Tue, 15 Oct 2019 13:00:03 +0200 Subject: [PATCH] Handle ListInitExpression in entity equality Closes #18379 --- .../EntityEqualityRewritingExpressionVisitor.cs | 10 ++++++++++ .../Query/SimpleQueryCosmosTest.Select.cs | 10 ++++++++++ .../Query/SimpleQueryTestBase.Select.cs | 12 ++++++++++++ .../Query/SimpleQuerySqlServerTest.Select.cs | 9 +++++++++ 4 files changed, 41 insertions(+) diff --git a/src/EFCore/Query/Internal/EntityEqualityRewritingExpressionVisitor.cs b/src/EFCore/Query/Internal/EntityEqualityRewritingExpressionVisitor.cs index 1378e2d1bf9..8e121ccefc0 100644 --- a/src/EFCore/Query/Internal/EntityEqualityRewritingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/EntityEqualityRewritingExpressionVisitor.cs @@ -138,6 +138,16 @@ protected override Expression VisitMemberInit(MemberInitExpression memberInitExp protected override Expression VisitNewArray(NewArrayExpression newArrayExpression) => newArrayExpression.Update(Visit(newArrayExpression.Expressions).Select(Unwrap)); + // Note that we could bubble up entity type information from the expressions initializing the list. However, EF Core doesn't + // actually support doing much further with this list, so it's not worth the complexity (right now). So we simply unwrap. + protected override Expression VisitListInit(ListInitExpression listInitExpression) + => listInitExpression.Update( + (NewExpression)Unwrap(listInitExpression.NewExpression), + listInitExpression.Initializers.Select(VisitElementInit)); + + protected override ElementInit VisitElementInit(ElementInit elementInit) + => Expression.ElementInit(elementInit.AddMethod, Visit(elementInit.Arguments).Select(Unwrap)); + protected override Expression VisitMember(MemberExpression memberExpression) { var visitedExpression = base.Visit(memberExpression.Expression); diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/SimpleQueryCosmosTest.Select.cs b/test/EFCore.Cosmos.FunctionalTests/Query/SimpleQueryCosmosTest.Select.cs index 3cfaca4f489..1eaab854326 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/SimpleQueryCosmosTest.Select.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/SimpleQueryCosmosTest.Select.cs @@ -106,6 +106,16 @@ FROM root c WHERE (c[""Discriminator""] = ""Customer"")"); } + public override async Task Projection_of_entity_type_into_object_list(bool isAsync) + { + await base.Projection_of_entity_type_into_object_list(isAsync); + + AssertSql( + @"SELECT c +FROM root c +WHERE (c[""Discriminator""] = ""Customer"")"); + } + public override async Task Project_to_int_array(bool isAsync) { await base.Project_to_int_array(isAsync); diff --git a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.Select.cs b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.Select.cs index 10d6fa42825..e60be56eb90 100644 --- a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.Select.cs +++ b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.Select.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore.Diagnostics; @@ -90,6 +91,17 @@ public virtual Task Projection_of_multiple_entity_types_into_object_array(bool i assertOrder: true); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Projection_of_entity_type_into_object_list(bool isAsync) + { + return AssertQuery( + isAsync, + ss => ss.Set().Select(c => new List { c }), + entryCount: 91, + assertOrder: true); + } + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Project_to_int_array(bool isAsync) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.Select.cs b/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.Select.cs index 7087beceb63..ee4783187f0 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.Select.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.Select.cs @@ -102,6 +102,15 @@ WHERE [o].[OrderID] < 10300 ORDER BY [o].[OrderID]"); } + public override async Task Projection_of_entity_type_into_object_list(bool isAsync) + { + await base.Projection_of_entity_type_into_object_list(isAsync); + + AssertSql( + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] +FROM [Customers] AS [c]"); + } + public override async Task Project_to_int_array(bool isAsync) { await base.Project_to_int_array(isAsync);