diff --git a/src/EFCore/Query/EntityQueryModelVisitor.cs b/src/EFCore/Query/EntityQueryModelVisitor.cs
index 6ab4064f91b..593251f1f69 100644
--- a/src/EFCore/Query/EntityQueryModelVisitor.cs
+++ b/src/EFCore/Query/EntityQueryModelVisitor.cs
@@ -300,6 +300,9 @@ protected virtual void OptimizeQueryModel(
_queryOptimizer.Optimize(QueryCompilationContext.QueryAnnotations, queryModel);
+ new MainFromClauseFlatteningQueryModelVisitor(QueryCompilationContext.QueryAnnotations)
+ .VisitQueryModel(queryModel);
+
var entityEqualityRewritingExpressionVisitor
= new EntityEqualityRewritingExpressionVisitor(QueryCompilationContext.Model);
diff --git a/src/EFCore/Query/ExpressionVisitors/Internal/MainFromClauseFlatteningQueryModelVisitor.cs b/src/EFCore/Query/ExpressionVisitors/Internal/MainFromClauseFlatteningQueryModelVisitor.cs
new file mode 100644
index 00000000000..3c64b26edd6
--- /dev/null
+++ b/src/EFCore/Query/ExpressionVisitors/Internal/MainFromClauseFlatteningQueryModelVisitor.cs
@@ -0,0 +1,101 @@
+// Copyright (c) .NET Foundation. All rights reserved.
+// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using JetBrains.Annotations;
+using Microsoft.EntityFrameworkCore.Query.Internal;
+using Microsoft.EntityFrameworkCore.Query.ResultOperators;
+using Remotion.Linq;
+using Remotion.Linq.Clauses;
+using Remotion.Linq.Clauses.Expressions;
+using Remotion.Linq.Clauses.ResultOperators;
+using Remotion.Linq.Parsing;
+
+namespace Microsoft.EntityFrameworkCore.Query.ExpressionVisitors.Internal
+{
+ ///
+ /// This API supports the Entity Framework Core infrastructure and is not intended to be used
+ /// directly from your code. This API may change or be removed in future releases.
+ ///
+ public class MainFromClauseFlatteningQueryModelVisitor : QueryModelVisitorBase
+ {
+ private readonly IEnumerable _queryAnnotations;
+ private readonly SubQueryExpressionVisitor _subQueryExpressionVisitor;
+
+ ///
+ /// This API supports the Entity Framework Core infrastructure and is not intended to be used
+ /// directly from your code. This API may change or be removed in future releases.
+ ///
+ public MainFromClauseFlatteningQueryModelVisitor([NotNull] IEnumerable queryAnnotations)
+ {
+ _queryAnnotations = queryAnnotations;
+ _subQueryExpressionVisitor = new SubQueryExpressionVisitor(this);
+ }
+
+ ///
+ /// This API supports the Entity Framework Core infrastructure and is not intended to be used
+ /// directly from your code. This API may change or be removed in future releases.
+ ///
+ public override void VisitQueryModel([NotNull] QueryModel queryModel)
+ {
+ queryModel.TransformExpressions(_subQueryExpressionVisitor.Visit);
+
+ base.VisitQueryModel(queryModel);
+ }
+
+ ///
+ /// This API supports the Entity Framework Core infrastructure and is not intended to be used
+ /// directly from your code. This API may change or be removed in future releases.
+ ///
+ public override void VisitMainFromClause([NotNull] MainFromClause fromClause, [NotNull] QueryModel queryModel)
+ {
+ if (fromClause.FromExpression is SubQueryExpression subQueryExpression)
+ {
+ var subQueryModel = subQueryExpression.QueryModel;
+
+ if (subQueryModel.SelectClause.Selector is QuerySourceReferenceExpression
+ && !subQueryModel.ResultOperators.OfType().Any()
+ && !queryModel.BodyClauses.Any())
+ {
+ queryModel.UpdateQuerySourceMapping(
+ queryModel.MainFromClause,
+ subQueryModel.SelectClause.Selector,
+ _queryAnnotations);
+
+ queryModel.MainFromClause = subQueryModel.MainFromClause;
+
+ foreach (var bodyClause in subQueryModel.BodyClauses)
+ {
+ queryModel.BodyClauses.Add(bodyClause);
+ }
+
+ foreach (var resultOperator in subQueryModel.ResultOperators.Reverse())
+ {
+ queryModel.ResultOperators.Insert(0, resultOperator);
+ }
+
+ return;
+ }
+ }
+ }
+
+ private class SubQueryExpressionVisitor : RelinqExpressionVisitor
+ {
+ private readonly MainFromClauseFlatteningQueryModelVisitor _queryModelVisitor;
+
+ public SubQueryExpressionVisitor(MainFromClauseFlatteningQueryModelVisitor queryModelVisitor)
+ {
+ _queryModelVisitor = queryModelVisitor;
+ }
+
+ protected override Expression VisitSubQuery(SubQueryExpression expression)
+ {
+ _queryModelVisitor.VisitQueryModel(expression.QueryModel);
+
+ return expression;
+ }
+ }
+ }
+}
diff --git a/src/EFCore/Query/Internal/QueryModelExtensions.cs b/src/EFCore/Query/Internal/QueryModelExtensions.cs
index e990f14c3b9..dd184eef518 100644
--- a/src/EFCore/Query/Internal/QueryModelExtensions.cs
+++ b/src/EFCore/Query/Internal/QueryModelExtensions.cs
@@ -5,9 +5,11 @@
using System.Linq.Expressions;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Query.ExpressionVisitors;
+using Microsoft.EntityFrameworkCore.Query.ResultOperators;
using Remotion.Linq;
using Remotion.Linq.Clauses;
using Remotion.Linq.Clauses.Expressions;
+using Remotion.Linq.Clauses.ExpressionVisitors;
namespace Microsoft.EntityFrameworkCore.Query.Internal
{
@@ -24,6 +26,52 @@ public static class QueryModelExtensions
public static string Print([NotNull] this QueryModel queryModel, bool removeFormatting = false, int? characterLimit = null)
=> new QueryModelPrinter().Print(queryModel, removeFormatting, characterLimit);
+ ///
+ /// This API supports the Entity Framework Core infrastructure and is not intended to be used
+ /// directly from your code. This API may change or be removed in future releases.
+ ///
+ public static void UpdateQuerySourceMapping(
+ [NotNull] this QueryModel queryModel,
+ [NotNull] IQuerySource oldQuerySource,
+ [NotNull] Expression newExpression,
+ [NotNull] IEnumerable queryAnnotations)
+ {
+ var querySourceMapping = new QuerySourceMapping();
+ querySourceMapping.AddMapping(oldQuerySource, newExpression);
+
+ queryModel.TransformExpressions(expression =>
+ ReferenceReplacingExpressionVisitor.ReplaceClauseReferences(
+ expression,
+ querySourceMapping,
+ throwOnUnmappedReferences: false));
+
+ if (newExpression is QuerySourceReferenceExpression qsre)
+ {
+ foreach (var queryAnnotation in queryAnnotations)
+ {
+ if (queryAnnotation.QuerySource == oldQuerySource)
+ {
+ queryAnnotation.QuerySource = qsre.ReferencedQuerySource;
+ queryAnnotation.QueryModel = queryModel;
+ }
+ }
+ }
+ }
+
+ ///
+ /// This API supports the Entity Framework Core infrastructure and is not intended to be used
+ /// directly from your code. This API may change or be removed in future releases.
+ ///
+ public static void UpdateQuerySourceMapping(
+ [NotNull] this QueryModel queryModel,
+ [NotNull] IQuerySource oldQuerySource,
+ [NotNull] IQuerySource newQuerySource,
+ [NotNull] IEnumerable queryAnnotations)
+ => queryModel.UpdateQuerySourceMapping(
+ oldQuerySource,
+ new QuerySourceReferenceExpression(newQuerySource),
+ queryAnnotations);
+
///
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
diff --git a/src/EFCore/Query/Internal/QueryOptimizer.cs b/src/EFCore/Query/Internal/QueryOptimizer.cs
index 7b3b077c888..b8d7614629d 100644
--- a/src/EFCore/Query/Internal/QueryOptimizer.cs
+++ b/src/EFCore/Query/Internal/QueryOptimizer.cs
@@ -13,7 +13,6 @@
using Remotion.Linq;
using Remotion.Linq.Clauses;
using Remotion.Linq.Clauses.Expressions;
-using Remotion.Linq.Clauses.ExpressionVisitors;
using Remotion.Linq.Clauses.ResultOperators;
using Remotion.Linq.Transformations;
@@ -102,9 +101,7 @@ public override void VisitJoinClause(JoinClause joinClause, QueryModel queryMode
private void TryFlattenJoin(JoinClause joinClause, QueryModel queryModel)
{
- var subQueryExpression = joinClause.InnerSequence as SubQueryExpression;
-
- if (subQueryExpression != null)
+ if (joinClause.InnerSequence is SubQueryExpression subQueryExpression)
{
VisitQueryModel(subQueryExpression.QueryModel);
@@ -135,29 +132,21 @@ public override void VisitGroupJoinClause(GroupJoinClause groupJoinClause, Query
// Attempts to rewrite GroupJoin/SelectMany to regular join
- var additionalFromClause
- = queryModel.BodyClauses.ElementAtOrDefault(index + 1)
- as AdditionalFromClause;
-
- var querySourceReferenceExpression
- = additionalFromClause?.FromExpression as QuerySourceReferenceExpression;
-
- if (querySourceReferenceExpression != null
- && querySourceReferenceExpression.ReferencedQuerySource == groupJoinClause)
+ if (queryModel.BodyClauses.ElementAtOrDefault(index + 1) is AdditionalFromClause additionalFromClause
+ && additionalFromClause.FromExpression is QuerySourceReferenceExpression qsre
+ && qsre.ReferencedQuerySource == groupJoinClause
+ && queryModel.CountQuerySourceReferences(groupJoinClause) == 1)
{
- if (queryModel.CountQuerySourceReferences(groupJoinClause) == 1)
- {
- // GroupJoin/SelectMany can be rewritten to regular Join.
+ // GroupJoin/SelectMany can be rewritten to regular Join.
- queryModel.BodyClauses.RemoveAt(index + 1);
- queryModel.BodyClauses.RemoveAt(index);
- queryModel.BodyClauses.Insert(index, groupJoinClause.JoinClause);
+ queryModel.BodyClauses.RemoveAt(index + 1);
+ queryModel.BodyClauses.RemoveAt(index);
+ queryModel.BodyClauses.Insert(index, groupJoinClause.JoinClause);
- UpdateQuerySourceMapping(
- queryModel,
- additionalFromClause,
- new QuerySourceReferenceExpression(groupJoinClause.JoinClause));
- }
+ queryModel.UpdateQuerySourceMapping(
+ additionalFromClause,
+ groupJoinClause.JoinClause,
+ _queryAnnotations);
}
}
@@ -175,11 +164,10 @@ protected override void FlattenSubQuery(
VisitQueryModel(subQueryModel);
- if (subQueryModel.ResultOperators
- .All(ro => ro is CastResultOperator)
- && !subQueryModel.BodyClauses.Any(bc => bc is OrderByClause)
- || queryModel.IsIdentityQuery()
- && !queryModel.ResultOperators.Any())
+ if ((subQueryModel.ResultOperators.All(ro => ro is CastResultOperator)
+ && !subQueryModel.BodyClauses.Any(bc => bc is OrderByClause))
+ || (queryModel.IsIdentityQuery()
+ && !queryModel.ResultOperators.Any()))
{
string itemName;
@@ -202,10 +190,10 @@ var fromClauseData
fromClause.CopyFromSource(fromClauseData);
- UpdateQuerySourceMapping(
- queryModel,
+ queryModel.UpdateQuerySourceMapping(
fromClause,
- subQueryExpression.QueryModel.SelectClause.Selector);
+ subQueryExpression.QueryModel.SelectClause.Selector,
+ _queryAnnotations);
InsertBodyClauses(subQueryExpression.QueryModel.BodyClauses, queryModel, destinationIndex);
@@ -214,10 +202,10 @@ var fromClauseData
queryModel.ResultOperators.Insert(0, resultOperator);
}
- UpdateQuerySourceMapping(
- queryModel,
+ queryModel.UpdateQuerySourceMapping(
innerMainFromClause,
- new QuerySourceReferenceExpression(fromClause));
+ new QuerySourceReferenceExpression(fromClause),
+ _queryAnnotations);
}
}
@@ -240,25 +228,25 @@ public override void VisitResultOperator(ResultOperatorBase resultOperator, Quer
}
}
}
-
- var ofTypeOperator = resultOperator as OfTypeResultOperator;
- if (ofTypeOperator != null)
+
+ if (resultOperator is OfTypeResultOperator ofTypeOperator)
{
- var searchedItemType = ofTypeOperator.SearchedItemType;
- if (searchedItemType == queryModel.MainFromClause.ItemType)
+ if (ofTypeOperator.SearchedItemType == queryModel.MainFromClause.ItemType)
{
queryModel.ResultOperators.RemoveAt(index);
}
else
{
- var entityType = _model.FindEntityType(searchedItemType);
+ var entityType = _model.FindEntityType(ofTypeOperator.SearchedItemType);
if (entityType != null)
{
var oldQuerySource = queryModel.MainFromClause;
var entityQueryProvider
- = ((oldQuerySource.FromExpression as ConstantExpression)?.Value as IQueryable)?.Provider as IAsyncQueryProvider;
+ = ((oldQuerySource.FromExpression as ConstantExpression)
+ ?.Value as IQueryable)
+ ?.Provider as IAsyncQueryProvider;
if (entityQueryProvider != null)
{
@@ -272,9 +260,10 @@ var newMainFromClause
queryModel.MainFromClause = newMainFromClause;
- UpdateQuerySourceMapping(queryModel,
+ queryModel.UpdateQuerySourceMapping(
oldQuerySource,
- new QuerySourceReferenceExpression(newMainFromClause));
+ newMainFromClause,
+ _queryAnnotations);
}
}
}
@@ -282,29 +271,5 @@ var newMainFromClause
base.VisitResultOperator(resultOperator, queryModel, index);
}
-
- private void UpdateQuerySourceMapping(
- QueryModel queryModel,
- IQuerySource oldQuerySource,
- Expression newExpression)
- {
- var querySourceMapping = new QuerySourceMapping();
- querySourceMapping.AddMapping(oldQuerySource, newExpression);
-
- queryModel.TransformExpressions(e =>
- ReferenceReplacingExpressionVisitor
- .ReplaceClauseReferences(e, querySourceMapping, throwOnUnmappedReferences: false));
-
- var qsre = newExpression as QuerySourceReferenceExpression;
- if (qsre != null)
- {
- var newQuerySource = qsre.ReferencedQuerySource;
- foreach (var queryAnnotation in _queryAnnotations.Where(qa => qa.QuerySource == oldQuerySource))
- {
- queryAnnotation.QuerySource = newQuerySource;
- queryAnnotation.QueryModel = queryModel;
- }
- }
- }
}
}
diff --git a/test/EFCore.SqlServer.FunctionalTests/ComplexNavigationsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/ComplexNavigationsQuerySqlServerTest.cs
index 710694be423..8eb184f4d05 100644
--- a/test/EFCore.SqlServer.FunctionalTests/ComplexNavigationsQuerySqlServerTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/ComplexNavigationsQuerySqlServerTest.cs
@@ -1868,13 +1868,10 @@ public override void Projection_select_correct_table_from_subquery_when_material
Assert.Equal(
@"@__p_0: 3
-SELECT [t].[Name]
-FROM (
- SELECT TOP(@__p_0) [l2].*
- FROM [Level2] AS [l2]
- INNER JOIN [Level1] AS [l2.OneToOne_Required_FK_Inverse] ON [l2].[Level1_Required_Id] = [l2.OneToOne_Required_FK_Inverse].[Id]
- WHERE [l2.OneToOne_Required_FK_Inverse].[Name] = N'L1 03'
-) AS [t]",
+SELECT TOP(@__p_0) [l2].[Name]
+FROM [Level2] AS [l2]
+INNER JOIN [Level1] AS [l2.OneToOne_Required_FK_Inverse] ON [l2].[Level1_Required_Id] = [l2.OneToOne_Required_FK_Inverse].[Id]
+WHERE [l2.OneToOne_Required_FK_Inverse].[Name] = N'L1 03'",
Sql);
}
@@ -1900,14 +1897,11 @@ public override void Projection_select_correct_table_in_subquery_when_materializ
Assert.Equal(
@"@__p_0: 3
-SELECT [t].[Name]
-FROM (
- SELECT TOP(@__p_0) [l1].*
- FROM [Level2] AS [l2]
- INNER JOIN [Level1] AS [l1] ON [l2].[Level1_Required_Id] = [l1].[Id]
- INNER JOIN [Level3] AS [l3] ON [l1].[Id] = [l3].[Level2_Required_Id]
- WHERE ([l1].[Name] = N'L1 03') AND ([l3].[Name] = N'L3 08')
-) AS [t]",
+SELECT TOP(@__p_0) [l1].[Name]
+FROM [Level2] AS [l2]
+INNER JOIN [Level1] AS [l1] ON [l2].[Level1_Required_Id] = [l1].[Id]
+INNER JOIN [Level3] AS [l3] ON [l1].[Id] = [l3].[Level2_Required_Id]
+WHERE ([l1].[Name] = N'L1 03') AND ([l3].[Name] = N'L3 08')",
Sql);
}
@@ -2324,12 +2318,9 @@ public override void Contains_with_subquery_optional_navigation_and_constant_ite
FROM [Level1] AS [l1]
LEFT JOIN [Level2] AS [l1.OneToOne_Optional_FK] ON [l1].[Id] = [l1.OneToOne_Optional_FK].[Level1_Optional_Id]
WHERE 1 IN (
- SELECT [t].[Id]
- FROM (
- SELECT DISTINCT [l].*
- FROM [Level3] AS [l]
- WHERE [l1.OneToOne_Optional_FK].[Id] = [l].[OneToMany_Optional_InverseId]
- ) AS [t]
+ SELECT DISTINCT [l].[Id]
+ FROM [Level3] AS [l]
+ WHERE [l1.OneToOne_Optional_FK].[Id] = [l].[OneToMany_Optional_InverseId]
)",
Sql);
}
@@ -2350,15 +2341,10 @@ public override void GroupJoin_on_left_side_being_a_subquery()
Assert.Equal(
@"@__p_0: 2
-SELECT [t].[Id], [t].[Date], [t].[Name], [t].[OneToMany_Optional_Self_InverseId], [t].[OneToMany_Required_Self_InverseId], [t].[OneToOne_Optional_SelfId], [t].[c0], [t].[c1], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[c2], [t].[OneToMany_Optional_InverseId], [t].[c3], [t].[OneToMany_Required_InverseId], [t].[c4], [t].[OneToOne_Optional_PK_InverseId], [t].[c5], [x.OneToOne_Optional_FK].[Id], [x.OneToOne_Optional_FK].[Date], [x.OneToOne_Optional_FK].[Level1_Optional_Id], [x.OneToOne_Optional_FK].[Level1_Required_Id], [x.OneToOne_Optional_FK].[Name], [x.OneToOne_Optional_FK].[OneToMany_Optional_InverseId], [x.OneToOne_Optional_FK].[OneToMany_Optional_Self_InverseId], [x.OneToOne_Optional_FK].[OneToMany_Required_InverseId], [x.OneToOne_Optional_FK].[OneToMany_Required_Self_InverseId], [x.OneToOne_Optional_FK].[OneToOne_Optional_PK_InverseId], [x.OneToOne_Optional_FK].[OneToOne_Optional_SelfId]
-FROM (
- SELECT TOP(@__p_0) [l1].[Id], [l1].[Date], [l1].[Name], [l1].[OneToMany_Optional_Self_InverseId], [l1].[OneToMany_Required_Self_InverseId], [l1].[OneToOne_Optional_SelfId], [l1.OneToOne_Optional_FK].[Id] AS [c0], [l1.OneToOne_Optional_FK].[Date] AS [c1], [l1.OneToOne_Optional_FK].[Level1_Optional_Id], [l1.OneToOne_Optional_FK].[Level1_Required_Id], [l1.OneToOne_Optional_FK].[Name] AS [c2], [l1.OneToOne_Optional_FK].[OneToMany_Optional_InverseId], [l1.OneToOne_Optional_FK].[OneToMany_Optional_Self_InverseId] AS [c3], [l1.OneToOne_Optional_FK].[OneToMany_Required_InverseId], [l1.OneToOne_Optional_FK].[OneToMany_Required_Self_InverseId] AS [c4], [l1.OneToOne_Optional_FK].[OneToOne_Optional_PK_InverseId], [l1.OneToOne_Optional_FK].[OneToOne_Optional_SelfId] AS [c5]
- FROM [Level1] AS [l1]
- LEFT JOIN [Level2] AS [l1.OneToOne_Optional_FK] ON [l1].[Id] = [l1.OneToOne_Optional_FK].[Level1_Optional_Id]
- ORDER BY [l1.OneToOne_Optional_FK].[Name]
-) AS [t]
-LEFT JOIN [Level2] AS [x.OneToOne_Optional_FK] ON [t].[Id] = [x.OneToOne_Optional_FK].[Level1_Optional_Id]
-ORDER BY [t].[Name]",
+SELECT TOP(@__p_0) [l1].[Id], [l1].[Date], [l1].[Name], [l1].[OneToMany_Optional_Self_InverseId], [l1].[OneToMany_Required_Self_InverseId], [l1].[OneToOne_Optional_SelfId], [l1.OneToOne_Optional_FK].[Id], [l1.OneToOne_Optional_FK].[Date], [l1.OneToOne_Optional_FK].[Level1_Optional_Id], [l1.OneToOne_Optional_FK].[Level1_Required_Id], [l1.OneToOne_Optional_FK].[Name], [l1.OneToOne_Optional_FK].[OneToMany_Optional_InverseId], [l1.OneToOne_Optional_FK].[OneToMany_Optional_Self_InverseId], [l1.OneToOne_Optional_FK].[OneToMany_Required_InverseId], [l1.OneToOne_Optional_FK].[OneToMany_Required_Self_InverseId], [l1.OneToOne_Optional_FK].[OneToOne_Optional_PK_InverseId], [l1.OneToOne_Optional_FK].[OneToOne_Optional_SelfId]
+FROM [Level1] AS [l1]
+LEFT JOIN [Level2] AS [l1.OneToOne_Optional_FK] ON [l1].[Id] = [l1.OneToOne_Optional_FK].[Level1_Optional_Id]
+ORDER BY [l1.OneToOne_Optional_FK].[Name]",
Sql);
}
@@ -2538,13 +2524,10 @@ public override void Optional_navigation_in_subquery_with_unrelated_projection()
Assert.Equal(
@"@__p_0: 15
-SELECT [t].[Id], [t].[Date], [t].[Name], [t].[OneToMany_Optional_Self_InverseId], [t].[OneToMany_Required_Self_InverseId], [t].[OneToOne_Optional_SelfId], [t].[c0], [t].[c1], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[c2], [t].[OneToMany_Optional_InverseId], [t].[c3], [t].[OneToMany_Required_InverseId], [t].[c4], [t].[OneToOne_Optional_PK_InverseId], [t].[c5]
-FROM (
- SELECT TOP(@__p_0) [l1].[Id], [l1].[Date], [l1].[Name], [l1].[OneToMany_Optional_Self_InverseId], [l1].[OneToMany_Required_Self_InverseId], [l1].[OneToOne_Optional_SelfId], [l1.OneToOne_Optional_FK].[Id] AS [c0], [l1.OneToOne_Optional_FK].[Date] AS [c1], [l1.OneToOne_Optional_FK].[Level1_Optional_Id], [l1.OneToOne_Optional_FK].[Level1_Required_Id], [l1.OneToOne_Optional_FK].[Name] AS [c2], [l1.OneToOne_Optional_FK].[OneToMany_Optional_InverseId], [l1.OneToOne_Optional_FK].[OneToMany_Optional_Self_InverseId] AS [c3], [l1.OneToOne_Optional_FK].[OneToMany_Required_InverseId], [l1.OneToOne_Optional_FK].[OneToMany_Required_Self_InverseId] AS [c4], [l1.OneToOne_Optional_FK].[OneToOne_Optional_PK_InverseId], [l1.OneToOne_Optional_FK].[OneToOne_Optional_SelfId] AS [c5]
- FROM [Level1] AS [l1]
- LEFT JOIN [Level2] AS [l1.OneToOne_Optional_FK] ON [l1].[Id] = [l1.OneToOne_Optional_FK].[Level1_Optional_Id]
- WHERE ([l1.OneToOne_Optional_FK].[Name] <> N'Foo') OR [l1.OneToOne_Optional_FK].[Name] IS NULL
-) AS [t]",
+SELECT TOP(@__p_0) [l1].[Id], [l1].[Date], [l1].[Name], [l1].[OneToMany_Optional_Self_InverseId], [l1].[OneToMany_Required_Self_InverseId], [l1].[OneToOne_Optional_SelfId], [l1.OneToOne_Optional_FK].[Id], [l1.OneToOne_Optional_FK].[Date], [l1.OneToOne_Optional_FK].[Level1_Optional_Id], [l1.OneToOne_Optional_FK].[Level1_Required_Id], [l1.OneToOne_Optional_FK].[Name], [l1.OneToOne_Optional_FK].[OneToMany_Optional_InverseId], [l1.OneToOne_Optional_FK].[OneToMany_Optional_Self_InverseId], [l1.OneToOne_Optional_FK].[OneToMany_Required_InverseId], [l1.OneToOne_Optional_FK].[OneToMany_Required_Self_InverseId], [l1.OneToOne_Optional_FK].[OneToOne_Optional_PK_InverseId], [l1.OneToOne_Optional_FK].[OneToOne_Optional_SelfId]
+FROM [Level1] AS [l1]
+LEFT JOIN [Level2] AS [l1.OneToOne_Optional_FK] ON [l1].[Id] = [l1.OneToOne_Optional_FK].[Level1_Optional_Id]
+WHERE ([l1.OneToOne_Optional_FK].[Name] <> N'Foo') OR [l1.OneToOne_Optional_FK].[Name] IS NULL",
Sql);
}
@@ -2555,13 +2538,10 @@ public override void Explicit_GroupJoin_in_subquery_with_unrelated_projection()
Assert.Equal(
@"@__p_0: 15
-SELECT [t].[Id], [t].[Date], [t].[Name], [t].[OneToMany_Optional_Self_InverseId], [t].[OneToMany_Required_Self_InverseId], [t].[OneToOne_Optional_SelfId], [t].[c0], [t].[c1], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[c2], [t].[OneToMany_Optional_InverseId], [t].[c3], [t].[OneToMany_Required_InverseId], [t].[c4], [t].[OneToOne_Optional_PK_InverseId], [t].[c5]
-FROM (
- SELECT TOP(@__p_0) [l1].[Id], [l1].[Date], [l1].[Name], [l1].[OneToMany_Optional_Self_InverseId], [l1].[OneToMany_Required_Self_InverseId], [l1].[OneToOne_Optional_SelfId], [l2].[Id] AS [c0], [l2].[Date] AS [c1], [l2].[Level1_Optional_Id], [l2].[Level1_Required_Id], [l2].[Name] AS [c2], [l2].[OneToMany_Optional_InverseId], [l2].[OneToMany_Optional_Self_InverseId] AS [c3], [l2].[OneToMany_Required_InverseId], [l2].[OneToMany_Required_Self_InverseId] AS [c4], [l2].[OneToOne_Optional_PK_InverseId], [l2].[OneToOne_Optional_SelfId] AS [c5]
- FROM [Level1] AS [l1]
- LEFT JOIN [Level2] AS [l2] ON [l1].[Id] = [l2].[Level1_Optional_Id]
- WHERE ([l2].[Name] <> N'Foo') OR [l2].[Name] IS NULL
-) AS [t]",
+SELECT TOP(@__p_0) [l1].[Id], [l1].[Date], [l1].[Name], [l1].[OneToMany_Optional_Self_InverseId], [l1].[OneToMany_Required_Self_InverseId], [l1].[OneToOne_Optional_SelfId], [l2].[Id], [l2].[Date], [l2].[Level1_Optional_Id], [l2].[Level1_Required_Id], [l2].[Name], [l2].[OneToMany_Optional_InverseId], [l2].[OneToMany_Optional_Self_InverseId], [l2].[OneToMany_Required_InverseId], [l2].[OneToMany_Required_Self_InverseId], [l2].[OneToOne_Optional_PK_InverseId], [l2].[OneToOne_Optional_SelfId]
+FROM [Level1] AS [l1]
+LEFT JOIN [Level2] AS [l2] ON [l1].[Id] = [l2].[Level1_Optional_Id]
+WHERE ([l2].[Name] <> N'Foo') OR [l2].[Name] IS NULL",
Sql);
}
@@ -2570,10 +2550,10 @@ public override void Explicit_GroupJoin_in_subquery_with_unrelated_projection2()
base.Explicit_GroupJoin_in_subquery_with_unrelated_projection2();
Assert.Equal(
- @"SELECT [l10].[Id], [l10].[Date], [l10].[Name], [l10].[OneToMany_Optional_Self_InverseId], [l10].[OneToMany_Required_Self_InverseId], [l10].[OneToOne_Optional_SelfId], [l20].[Id], [l20].[Date], [l20].[Level1_Optional_Id], [l20].[Level1_Required_Id], [l20].[Name], [l20].[OneToMany_Optional_InverseId], [l20].[OneToMany_Optional_Self_InverseId], [l20].[OneToMany_Required_InverseId], [l20].[OneToMany_Required_Self_InverseId], [l20].[OneToOne_Optional_PK_InverseId], [l20].[OneToOne_Optional_SelfId]
-FROM [Level1] AS [l10]
-LEFT JOIN [Level2] AS [l20] ON [l10].[Id] = [l20].[Level1_Optional_Id]
-WHERE ([l20].[Name] <> N'Foo') OR [l20].[Name] IS NULL",
+ @"SELECT [l1].[Id], [l1].[Date], [l1].[Name], [l1].[OneToMany_Optional_Self_InverseId], [l1].[OneToMany_Required_Self_InverseId], [l1].[OneToOne_Optional_SelfId], [l2].[Id], [l2].[Date], [l2].[Level1_Optional_Id], [l2].[Level1_Required_Id], [l2].[Name], [l2].[OneToMany_Optional_InverseId], [l2].[OneToMany_Optional_Self_InverseId], [l2].[OneToMany_Required_InverseId], [l2].[OneToMany_Required_Self_InverseId], [l2].[OneToOne_Optional_PK_InverseId], [l2].[OneToOne_Optional_SelfId]
+FROM [Level1] AS [l1]
+LEFT JOIN [Level2] AS [l2] ON [l1].[Id] = [l2].[Level1_Optional_Id]
+WHERE ([l2].[Name] <> N'Foo') OR [l2].[Name] IS NULL",
Sql);
}
@@ -2645,17 +2625,13 @@ public override void Where_on_multilevel_reference_in_subquery_with_outer_projec
@"@__p_0: 0
@__p_1: 10
-SELECT [t].[Name]
-FROM (
- SELECT [l3].*
- FROM [Level3] AS [l3]
- INNER JOIN [Level2] AS [l3.OneToMany_Required_Inverse] ON [l3].[OneToMany_Required_InverseId] = [l3.OneToMany_Required_Inverse].[Id]
- INNER JOIN [Level1] AS [l3.OneToMany_Required_Inverse.OneToOne_Required_FK_Inverse] ON [l3.OneToMany_Required_Inverse].[Level1_Required_Id] = [l3.OneToMany_Required_Inverse.OneToOne_Required_FK_Inverse].[Id]
- WHERE [l3.OneToMany_Required_Inverse.OneToOne_Required_FK_Inverse].[Name] = N'L1 03'
- ORDER BY [l3].[Level2_Required_Id]
- OFFSET @__p_0 ROWS FETCH NEXT @__p_1 ROWS ONLY
-) AS [t]
-ORDER BY [t].[Level2_Required_Id]",
+SELECT [l3].[Name]
+FROM [Level3] AS [l3]
+INNER JOIN [Level2] AS [l3.OneToMany_Required_Inverse] ON [l3].[OneToMany_Required_InverseId] = [l3.OneToMany_Required_Inverse].[Id]
+INNER JOIN [Level1] AS [l3.OneToMany_Required_Inverse.OneToOne_Required_FK_Inverse] ON [l3.OneToMany_Required_Inverse].[Level1_Required_Id] = [l3.OneToMany_Required_Inverse.OneToOne_Required_FK_Inverse].[Id]
+WHERE [l3.OneToMany_Required_Inverse.OneToOne_Required_FK_Inverse].[Name] = N'L1 03'
+ORDER BY [l3].[Level2_Required_Id]
+OFFSET @__p_0 ROWS FETCH NEXT @__p_1 ROWS ONLY",
Sql);
}
diff --git a/test/EFCore.SqlServer.FunctionalTests/IncludeSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/IncludeSqlServerTest.cs
index 0bfa190e4ac..41cfc00f5d2 100644
--- a/test/EFCore.SqlServer.FunctionalTests/IncludeSqlServerTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/IncludeSqlServerTest.cs
@@ -937,15 +937,11 @@ public override void Include_where_skip_take_projection(bool useString)
@__p_1: 2
SELECT [od.Order].[CustomerID]
-FROM (
- SELECT [od].*
- FROM [Order Details] AS [od]
- WHERE [od].[Quantity] = 10
- ORDER BY [od].[OrderID], [od].[ProductID]
- OFFSET @__p_0 ROWS FETCH NEXT @__p_1 ROWS ONLY
-) AS [t]
-INNER JOIN [Orders] AS [od.Order] ON [t].[OrderID] = [od.Order].[OrderID]
-ORDER BY [t].[OrderID], [t].[ProductID]",
+FROM [Order Details] AS [od]
+INNER JOIN [Orders] AS [od.Order] ON [od].[OrderID] = [od.Order].[OrderID]
+WHERE [od].[Quantity] = 10
+ORDER BY [od].[OrderID], [od].[ProductID]
+OFFSET @__p_0 ROWS FETCH NEXT @__p_1 ROWS ONLY",
Sql);
}
}
diff --git a/test/EFCore.SqlServer.FunctionalTests/QueryNavigationsSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/QueryNavigationsSqlServerTest.cs
index 1bdbde4a390..e6e7a13eaab 100644
--- a/test/EFCore.SqlServer.FunctionalTests/QueryNavigationsSqlServerTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/QueryNavigationsSqlServerTest.cs
@@ -198,13 +198,9 @@ public override void Take_Select_Navigation()
Assert.Equal(
@"@__p_0: 2
-SELECT [t].[CustomerID]
-FROM (
- SELECT TOP(@__p_0) [c].*
- FROM [Customers] AS [c]
- ORDER BY [c].[CustomerID]
-) AS [t]
-ORDER BY [t].[CustomerID]
+SELECT TOP(@__p_0) [c].[CustomerID]
+FROM [Customers] AS [c]
+ORDER BY [c].[CustomerID]
@_outer_CustomerID: ALFKI (Size = 450)
@@ -227,17 +223,13 @@ public override void Select_collection_FirstOrDefault_project_single_column1()
Assert.Equal(
@"@__p_0: 2
-SELECT (
+SELECT TOP(@__p_0) (
SELECT TOP(1) [o].[CustomerID]
FROM [Orders] AS [o]
- WHERE [t].[CustomerID] = [o].[CustomerID]
+ WHERE [c].[CustomerID] = [o].[CustomerID]
)
-FROM (
- SELECT TOP(@__p_0) [c].*
- FROM [Customers] AS [c]
- ORDER BY [c].[CustomerID]
-) AS [t]
-ORDER BY [t].[CustomerID]",
+FROM [Customers] AS [c]
+ORDER BY [c].[CustomerID]",
Sql);
}
@@ -248,17 +240,13 @@ public override void Select_collection_FirstOrDefault_project_single_column2()
Assert.Equal(
@"@__p_0: 2
-SELECT (
+SELECT TOP(@__p_0) (
SELECT TOP(1) [o].[CustomerID]
FROM [Orders] AS [o]
- WHERE [t].[CustomerID] = [o].[CustomerID]
+ WHERE [c].[CustomerID] = [o].[CustomerID]
)
-FROM (
- SELECT TOP(@__p_0) [c].*
- FROM [Customers] AS [c]
- ORDER BY [c].[CustomerID]
-) AS [t]
-ORDER BY [t].[CustomerID]",
+FROM [Customers] AS [c]
+ORDER BY [c].[CustomerID]",
Sql);
}
@@ -269,13 +257,9 @@ public override void Select_collection_FirstOrDefault_project_anonymous_type()
Assert.Equal(
@"@__p_0: 2
-SELECT [t].[CustomerID]
-FROM (
- SELECT TOP(@__p_0) [c].*
- FROM [Customers] AS [c]
- ORDER BY [c].[CustomerID]
-) AS [t]
-ORDER BY [t].[CustomerID]
+SELECT TOP(@__p_0) [c].[CustomerID]
+FROM [Customers] AS [c]
+ORDER BY [c].[CustomerID]
@_outer_CustomerID: ALFKI (Size = 450)
@@ -298,13 +282,9 @@ public override void Select_collection_FirstOrDefault_project_entity()
Assert.Equal(
@"@__p_0: 2
-SELECT [t].[CustomerID]
-FROM (
- SELECT TOP(@__p_0) [c].*
- FROM [Customers] AS [c]
- ORDER BY [c].[CustomerID]
-) AS [t]
-ORDER BY [t].[CustomerID]
+SELECT TOP(@__p_0) [c].[CustomerID]
+FROM [Customers] AS [c]
+ORDER BY [c].[CustomerID]
@_outer_CustomerID: ALFKI (Size = 450)
@@ -329,14 +309,10 @@ public override void Skip_Select_Navigation()
Assert.StartsWith(
@"@__p_0: 20
-SELECT [t].[CustomerID]
-FROM (
- SELECT [c].*
- FROM [Customers] AS [c]
- ORDER BY [c].[CustomerID]
- OFFSET @__p_0 ROWS
-) AS [t]
-ORDER BY [t].[CustomerID]
+SELECT [c].[CustomerID]
+FROM [Customers] AS [c]
+ORDER BY [c].[CustomerID]
+OFFSET @__p_0 ROWS
@_outer_CustomerID: FAMIA (Size = 450)
diff --git a/test/EFCore.SqlServer.FunctionalTests/QuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/QuerySqlServerTest.cs
index 56a1083f2d4..8f35e66f914 100644
--- a/test/EFCore.SqlServer.FunctionalTests/QuerySqlServerTest.cs
+++ b/test/EFCore.SqlServer.FunctionalTests/QuerySqlServerTest.cs
@@ -1745,11 +1745,8 @@ public override void Queryable_simple_anonymous_projection_subquery()
Assert.Equal(
@"@__p_0: 91
-SELECT [t].[City]
-FROM (
- SELECT TOP(@__p_0) [c].*
- FROM [Customers] AS [c]
-) AS [t]",
+SELECT TOP(@__p_0) [c].[City]
+FROM [Customers] AS [c]",
Sql);
}
@@ -1811,13 +1808,9 @@ public override void Take_subquery_projection()
Assert.Equal(
@"@__p_0: 2
-SELECT [t].[City]
-FROM (
- SELECT TOP(@__p_0) [c].*
- FROM [Customers] AS [c]
- ORDER BY [c].[CustomerID]
-) AS [t]
-ORDER BY [t].[CustomerID]",
+SELECT TOP(@__p_0) [c].[City]
+FROM [Customers] AS [c]
+ORDER BY [c].[CustomerID]",
Sql);
}
@@ -2141,11 +2134,8 @@ public override void Select_scalar_primitive_after_take()
Assert.Equal(
@"@__p_0: 9
-SELECT [t].[EmployeeID]
-FROM (
- SELECT TOP(@__p_0) [e].*
- FROM [Employees] AS [e]
-) AS [t]",
+SELECT TOP(@__p_0) [e].[EmployeeID]
+FROM [Employees] AS [e]",
Sql);
}
@@ -5590,12 +5580,9 @@ FROM [Customers] AS [c]
@_outer_CustomerID: ALFKI (Size = 450)
-SELECT [t].[OrderDate]
-FROM (
- SELECT TOP(3) [o].*
- FROM [Orders] AS [o]
- WHERE ([o].[OrderID] < 10500) AND (@_outer_CustomerID = [o].[CustomerID])
-) AS [t]",
+SELECT TOP(3) [o].[OrderDate]
+FROM [Orders] AS [o]
+WHERE ([o].[OrderID] < 10500) AND (@_outer_CustomerID = [o].[CustomerID])",
Sql);
}
@@ -5611,15 +5598,12 @@ FROM [Customers] AS [c]
@_outer_City: Berlin (Size = 6)
@_outer_CustomerID: ALFKI (Size = 450)
-SELECT [t].[OrderDate]
-FROM (
- SELECT TOP(3) [o].*
- FROM [Orders] AS [o]
- WHERE EXISTS (
- SELECT 1
- FROM [Order Details] AS [d]
- WHERE ([d].[Discount] > LEN(@_outer_City)) AND ([o].[OrderID] = [d].[OrderID])) AND (@_outer_CustomerID = [o].[CustomerID])
-) AS [t]",
+SELECT TOP(3) [o].[OrderDate]
+FROM [Orders] AS [o]
+WHERE EXISTS (
+ SELECT 1
+ FROM [Order Details] AS [d]
+ WHERE ([d].[Discount] > LEN(@_outer_City)) AND ([o].[OrderID] = [d].[OrderID])) AND (@_outer_CustomerID = [o].[CustomerID])",
Sql);
}
@@ -5647,12 +5631,9 @@ THEN CAST(1 AS BIT) ELSE CAST(0 AS BIT)
@_outer_CustomerID: ALFKI (Size = 450)
-SELECT [t].[OrderDate]
-FROM (
- SELECT TOP(3) [o0].*
- FROM [Orders] AS [o0]
- WHERE @_outer_CustomerID = [o0].[CustomerID]
-) AS [t]",
+SELECT TOP(3) [o0].[OrderDate]
+FROM [Orders] AS [o0]
+WHERE @_outer_CustomerID = [o0].[CustomerID]",
Sql);
}