From d6da9832e26bc55e1854d918e6546163a82ebee9 Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Sun, 30 Jun 2019 18:43:26 -0700 Subject: [PATCH 1/3] Query: Convert MaterializeCollectionNavigation to expression from methodCall For easier processing in the tree --- ...ionalProjectionBindingExpressionVisitor.cs | 16 +++---- ...terializeCollectionNavigationExpression.cs | 45 +++++++++++++++++++ .../NavigationExpansionHelpers.cs | 15 ------- .../NavigationExpansionReducingVisitor.cs | 11 +---- 4 files changed, 54 insertions(+), 33 deletions(-) create mode 100644 src/EFCore/Query/NavigationExpansion/MaterializeCollectionNavigationExpression.cs diff --git a/src/EFCore.Relational/Query/Pipeline/RelationalProjectionBindingExpressionVisitor.cs b/src/EFCore.Relational/Query/Pipeline/RelationalProjectionBindingExpressionVisitor.cs index ec269e22e6f..19c65788b39 100644 --- a/src/EFCore.Relational/Query/Pipeline/RelationalProjectionBindingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Pipeline/RelationalProjectionBindingExpressionVisitor.cs @@ -95,16 +95,16 @@ public override Expression Visit(Expression expression) Expression.Constant(parameterExpression.Name)); } - if (expression is MethodCallExpression methodCallExpression) + if (expression is MaterializeCollectionNavigationExpression materializeCollectionNavigationExpression) { - if (methodCallExpression.Method.Name == "MaterializeCollectionNavigation") - { - var result = _queryableMethodTranslatingExpressionVisitor.TranslateSubquery(methodCallExpression.Arguments[0]); - var navigation = (INavigation)((ConstantExpression)methodCallExpression.Arguments[1]).Value; - - return _selectExpression.AddCollectionProjection(result, navigation, null); - } + return _selectExpression.AddCollectionProjection( + _queryableMethodTranslatingExpressionVisitor.TranslateSubquery( + materializeCollectionNavigationExpression.Subquery), + materializeCollectionNavigationExpression.Navigation, null); + } + if (expression is MethodCallExpression methodCallExpression) + { if (methodCallExpression.Method.IsGenericMethod && methodCallExpression.Method.DeclaringType == typeof(Enumerable) && methodCallExpression.Method.Name == nameof(Enumerable.ToList)) diff --git a/src/EFCore/Query/NavigationExpansion/MaterializeCollectionNavigationExpression.cs b/src/EFCore/Query/NavigationExpansion/MaterializeCollectionNavigationExpression.cs new file mode 100644 index 00000000000..ac5e6cf77cc --- /dev/null +++ b/src/EFCore/Query/NavigationExpansion/MaterializeCollectionNavigationExpression.cs @@ -0,0 +1,45 @@ +// 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; +using System.Linq.Expressions; +using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; +using Microsoft.EntityFrameworkCore.Query.Internal; + +namespace Microsoft.EntityFrameworkCore.Query.NavigationExpansion +{ + public class MaterializeCollectionNavigationExpression : Expression, IPrintable + { + public MaterializeCollectionNavigationExpression(Expression subquery, INavigation navigation) + { + Subquery = subquery; + Navigation = navigation; + } + + public virtual Expression Subquery { get; } + public virtual INavigation Navigation { get; } + + public override ExpressionType NodeType => ExpressionType.Extension; + public override Type Type => Navigation.ClrType; + + public virtual void Print(ExpressionPrinter expressionPrinter) + { + expressionPrinter.StringBuilder.Append($"MaterializeCollectionNavigation({Navigation}, "); + expressionPrinter.Visit(Subquery); + expressionPrinter.StringBuilder.Append(")"); + } + + protected override Expression VisitChildren(ExpressionVisitor visitor) + { + var subquery = visitor.Visit(Subquery); + + return subquery != Subquery + ? new MaterializeCollectionNavigationExpression(subquery, Navigation) + : this; + } + + + } +} diff --git a/src/EFCore/Query/NavigationExpansion/NavigationExpansionHelpers.cs b/src/EFCore/Query/NavigationExpansion/NavigationExpansionHelpers.cs index 14552be1632..fdb03ca2d5e 100644 --- a/src/EFCore/Query/NavigationExpansion/NavigationExpansionHelpers.cs +++ b/src/EFCore/Query/NavigationExpansion/NavigationExpansionHelpers.cs @@ -8,7 +8,6 @@ using System.Reflection; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; -using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; using Microsoft.EntityFrameworkCore.Query.Internal; @@ -276,19 +275,5 @@ public static Expression CreateNullKeyExpression(Type resultType, int keyCount) Expression.Constant(null), keyCount))) : (Expression)Expression.Constant(null); - - public static readonly MethodInfo MaterializeCollectionNavigationMethodInfo - = typeof(NavigationExpansionHelpers).GetTypeInfo() - .GetDeclaredMethod(nameof(MaterializeCollectionNavigation)); - - public static TResult MaterializeCollectionNavigation( - IEnumerable elements, - INavigation navigation) - where TResult : IEnumerable - { - var collection = navigation.GetCollectionAccessor().Create(elements); - - return (TResult)collection; - } } } diff --git a/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpansionReducingVisitor.cs b/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpansionReducingVisitor.cs index c0f601d449d..0026f24c2f0 100644 --- a/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpansionReducingVisitor.cs +++ b/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpansionReducingVisitor.cs @@ -83,16 +83,7 @@ protected override Expression VisitExtension(Expression extensionExpression) if (state.MaterializeCollectionNavigation != null) { - var entityType = state.MaterializeCollectionNavigation.ClrType.IsGenericType - ? state.MaterializeCollectionNavigation.ClrType.GetGenericArguments()[0] - : state.MaterializeCollectionNavigation.GetTargetType().ClrType; - - result = Expression.Call( - NavigationExpansionHelpers.MaterializeCollectionNavigationMethodInfo.MakeGenericMethod( - state.MaterializeCollectionNavigation.ClrType, - entityType), - result, - Expression.Constant(state.MaterializeCollectionNavigation)); + result = new MaterializeCollectionNavigationExpression(result, state.MaterializeCollectionNavigation); } if (navigationExpansionExpression.Type != result.Type && navigationExpansionExpression.Type.IsGenericType) From 61e28d3c48b4301182801ae1f8b998f8073c20e8 Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Sun, 30 Jun 2019 19:22:15 -0700 Subject: [PATCH 2/3] Query: Add support for TagWith in relational layer Close #15710 --- ...osShapedQueryCompilingExpressionVisitor.cs | 13 +++--- ...dQueryCompilingExpressionVisitorFactory.cs | 7 +--- .../InMemoryShapedQueryExpressionVisitor.cs | 12 +++--- ...moryShapedQueryExpressionVisitorFactory.cs | 7 +--- .../Query/Pipeline/QuerySqlGenerator.cs | 42 +++++++++++++++++-- ...alShapedQueryCompilingExpressionVisitor.cs | 16 +++---- ...onalShapedQueryExpressionVisitorFactory.cs | 7 +--- .../SqlExpressions/SelectExpression.cs | 9 ++-- .../NavigationExpansionExpression.cs | 1 - .../NavigationExpansionExpressionState.cs | 3 -- .../NavigationExpansionHelpers.cs | 1 - .../Visitors/NavigationExpandingVisitor.cs | 4 -- .../NavigationExpandingVisitor_MethodCall.cs | 20 --------- .../NavigationExpansionReducingVisitor.cs | 11 ----- .../Query/Pipeline/QueryCompilationContext.cs | 7 ++++ ...ueryMetadataExtractingExpressionVisitor.cs | 9 ++++ .../QueryOptimizingExpressionVisitor.cs | 2 +- .../Pipeline/ShapedQueryExpressionVisitor.cs | 12 +++--- .../Query/QueryTaggingSqlServerTest.cs | 37 ++++++++-------- .../SqlServerComplianceTest.cs | 1 - 20 files changed, 109 insertions(+), 112 deletions(-) diff --git a/src/EFCore.Cosmos/Query/Pipeline/CosmosShapedQueryCompilingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Pipeline/CosmosShapedQueryCompilingExpressionVisitor.cs index 276de32cd55..b98b0ab41cb 100644 --- a/src/EFCore.Cosmos/Query/Pipeline/CosmosShapedQueryCompilingExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Pipeline/CosmosShapedQueryCompilingExpressionVisitor.cs @@ -32,19 +32,16 @@ public class CosmosShapedQueryCompilingExpressionVisitor : ShapedQueryCompilingE private readonly IDiagnosticsLogger _logger; public CosmosShapedQueryCompilingExpressionVisitor( + QueryCompilationContext queryCompilationContext, IEntityMaterializerSource entityMaterializerSource, ISqlExpressionFactory sqlExpressionFactory, - IQuerySqlGeneratorFactory querySqlGeneratorFactory, - Type contextType, - IDiagnosticsLogger logger, - bool trackQueryResults, - bool async) - : base(entityMaterializerSource, trackQueryResults, async) + IQuerySqlGeneratorFactory querySqlGeneratorFactory) + : base(queryCompilationContext, entityMaterializerSource) { _sqlExpressionFactory = sqlExpressionFactory; _querySqlGeneratorFactory = querySqlGeneratorFactory; - _contextType = contextType; - _logger = logger; + _contextType = queryCompilationContext.ContextType; + _logger = queryCompilationContext.Logger; } protected override Expression VisitShapedQueryExpression(ShapedQueryExpression shapedQueryExpression) diff --git a/src/EFCore.Cosmos/Query/Pipeline/CosmosShapedQueryCompilingExpressionVisitorFactory.cs b/src/EFCore.Cosmos/Query/Pipeline/CosmosShapedQueryCompilingExpressionVisitorFactory.cs index 6f9961e1a82..d65007f20a8 100644 --- a/src/EFCore.Cosmos/Query/Pipeline/CosmosShapedQueryCompilingExpressionVisitorFactory.cs +++ b/src/EFCore.Cosmos/Query/Pipeline/CosmosShapedQueryCompilingExpressionVisitorFactory.cs @@ -25,13 +25,10 @@ public CosmosShapedQueryCompilingExpressionVisitorFactory(IEntityMaterializerSou public ShapedQueryCompilingExpressionVisitor Create(QueryCompilationContext queryCompilationContext) { return new CosmosShapedQueryCompilingExpressionVisitor( + queryCompilationContext, _entityMaterializerSource, _sqlExpressionFactory, - _querySqlGeneratorFactory, - queryCompilationContext.ContextType, - queryCompilationContext.Logger, - queryCompilationContext.TrackQueryResults, - queryCompilationContext.Async); + _querySqlGeneratorFactory); } } } diff --git a/src/EFCore.InMemory/Query/Pipeline/InMemoryShapedQueryExpressionVisitor.cs b/src/EFCore.InMemory/Query/Pipeline/InMemoryShapedQueryExpressionVisitor.cs index 549efa163d0..6d4b7a9ec09 100644 --- a/src/EFCore.InMemory/Query/Pipeline/InMemoryShapedQueryExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Pipeline/InMemoryShapedQueryExpressionVisitor.cs @@ -26,14 +26,12 @@ public class InMemoryShapedQueryCompilingExpressionVisitor : ShapedQueryCompilin private readonly IDiagnosticsLogger _logger; public InMemoryShapedQueryCompilingExpressionVisitor( - IEntityMaterializerSource entityMaterializerSource, - Type contextType, - IDiagnosticsLogger logger, - bool trackQueryResults, bool async) - : base(entityMaterializerSource, trackQueryResults, async) + QueryCompilationContext queryCompilationContext, + IEntityMaterializerSource entityMaterializerSource) + : base(queryCompilationContext, entityMaterializerSource) { - _contextType = contextType; - _logger = logger; + _contextType = queryCompilationContext.ContextType; + _logger = queryCompilationContext.Logger; } protected override Expression VisitExtension(Expression extensionExpression) diff --git a/src/EFCore.InMemory/Query/Pipeline/InMemoryShapedQueryExpressionVisitorFactory.cs b/src/EFCore.InMemory/Query/Pipeline/InMemoryShapedQueryExpressionVisitorFactory.cs index c9ad4e98ced..e4808cdb5c3 100644 --- a/src/EFCore.InMemory/Query/Pipeline/InMemoryShapedQueryExpressionVisitorFactory.cs +++ b/src/EFCore.InMemory/Query/Pipeline/InMemoryShapedQueryExpressionVisitorFactory.cs @@ -19,11 +19,8 @@ public InMemoryShapedQueryCompilingExpressionVisitorFactory(IEntityMaterializerS public ShapedQueryCompilingExpressionVisitor Create(QueryCompilationContext queryCompilationContext) { return new InMemoryShapedQueryCompilingExpressionVisitor( - _entityMaterializerSource, - queryCompilationContext.ContextType, - queryCompilationContext.Logger, - queryCompilationContext.TrackQueryResults, - queryCompilationContext.Async); + queryCompilationContext, + _entityMaterializerSource); } } diff --git a/src/EFCore.Relational/Query/Pipeline/QuerySqlGenerator.cs b/src/EFCore.Relational/Query/Pipeline/QuerySqlGenerator.cs index ea528ba5e10..5d8597b7616 100644 --- a/src/EFCore.Relational/Query/Pipeline/QuerySqlGenerator.cs +++ b/src/EFCore.Relational/Query/Pipeline/QuerySqlGenerator.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Linq; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; @@ -55,14 +56,46 @@ public virtual IRelationalCommand GetCommand(SelectExpression selectExpression) } else { + GenerateTagsHeaderComment(selectExpression); + VisitSelect(selectExpression); } return _relationalCommandBuilder.Build(); } + /// + /// The default alias separator. + /// + protected virtual string AliasSeparator { get; } = " AS "; + + /// + /// The default single line comment prefix. + /// + protected virtual string SingleLineCommentToken { get; } = "--"; + protected virtual IRelationalCommandBuilder Sql => _relationalCommandBuilder; + protected virtual void GenerateTagsHeaderComment(SelectExpression selectExpression) + { + if (selectExpression.Tags.Count > 0) + { + foreach (var tag in selectExpression.Tags) + { + using (var reader = new StringReader(tag)) + { + string line; + while ((line = reader.ReadLine()) != null) + { + _relationalCommandBuilder.Append(SingleLineCommentToken).Append(" ").AppendLine(line); + } + } + + _relationalCommandBuilder.AppendLine(); + } + } + } + protected override Expression VisitSqlFragment(SqlFragmentExpression sqlFragmentExpression) { _relationalCommandBuilder.Append(sqlFragmentExpression.Sql); @@ -94,7 +127,7 @@ protected override Expression VisitSelect(SelectExpression selectExpression) subQueryIndent.Dispose(); _relationalCommandBuilder.AppendLine() - .Append(") AS " + _sqlGenerationHelper.DelimitIdentifier(selectExpression.Alias)); + .Append(")" + AliasSeparator + _sqlGenerationHelper.DelimitIdentifier(selectExpression.Alias)); } return selectExpression; @@ -193,7 +226,7 @@ protected override Expression VisitProjection(ProjectionExpression projectionExp && !(projectionExpression.Expression is ColumnExpression column && string.Equals(column.Name, projectionExpression.Alias))) { - _relationalCommandBuilder.Append(" AS " + _sqlGenerationHelper.DelimitIdentifier(projectionExpression.Alias)); + _relationalCommandBuilder.Append(AliasSeparator + _sqlGenerationHelper.DelimitIdentifier(projectionExpression.Alias)); } return projectionExpression; @@ -248,7 +281,7 @@ protected override Expression VisitTable(TableExpression tableExpression) { _relationalCommandBuilder .Append(_sqlGenerationHelper.DelimitIdentifier(tableExpression.Table, tableExpression.Schema)) - .Append(" AS ") + .Append(AliasSeparator) .Append(_sqlGenerationHelper.DelimitIdentifier(tableExpression.Alias)); return tableExpression; @@ -297,7 +330,8 @@ protected override Expression VisitFromSql(FromSqlExpression fromSqlExpression) GenerateFromSql(fromSqlExpression); } - _relationalCommandBuilder.Append(") AS ") + _relationalCommandBuilder.Append(")") + .Append(AliasSeparator) .Append(_sqlGenerationHelper.DelimitIdentifier(fromSqlExpression.Alias)); return fromSqlExpression; diff --git a/src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryCompilingExpressionVisitor.cs b/src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryCompilingExpressionVisitor.cs index 7859bef6cb2..b228b0d9f3c 100644 --- a/src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryCompilingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryCompilingExpressionVisitor.cs @@ -22,28 +22,28 @@ public partial class RelationalShapedQueryCompilingExpressionVisitor : ShapedQue private readonly IParameterNameGeneratorFactory _parameterNameGeneratorFactory; private readonly Type _contextType; private readonly IDiagnosticsLogger _logger; + private readonly ISet _tags; public RelationalShapedQueryCompilingExpressionVisitor( + QueryCompilationContext queryCompilationContext, IEntityMaterializerSource entityMaterializerSource, IQuerySqlGeneratorFactory querySqlGeneratorFactory, ISqlExpressionFactory sqlExpressionFactory, - IParameterNameGeneratorFactory parameterNameGeneratorFactory, - Type contextType, - IDiagnosticsLogger logger, - bool trackQueryResults, - bool async) - : base(entityMaterializerSource, trackQueryResults, async) + IParameterNameGeneratorFactory parameterNameGeneratorFactory) + : base(queryCompilationContext, entityMaterializerSource) { _querySqlGeneratorFactory = querySqlGeneratorFactory; _sqlExpressionFactory = sqlExpressionFactory; _parameterNameGeneratorFactory = parameterNameGeneratorFactory; - _contextType = contextType; - _logger = logger; + _contextType = queryCompilationContext.ContextType; + _logger = queryCompilationContext.Logger; + _tags = queryCompilationContext.Tags; } protected override Expression VisitShapedQueryExpression(ShapedQueryExpression shapedQueryExpression) { var selectExpression = (SelectExpression)shapedQueryExpression.QueryExpression; + selectExpression.ApplyTags(_tags); var dataReaderParameter = Expression.Parameter(typeof(DbDataReader), "dataReader"); var resultCoordinatorParameter = Expression.Parameter(typeof(ResultCoordinator), "resultCoordinator"); diff --git a/src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryExpressionVisitorFactory.cs b/src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryExpressionVisitorFactory.cs index e35c23aa3f1..7b828473d02 100644 --- a/src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryExpressionVisitorFactory.cs +++ b/src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryExpressionVisitorFactory.cs @@ -30,14 +30,11 @@ public RelationalShapedQueryCompilingExpressionVisitorFactory( public ShapedQueryCompilingExpressionVisitor Create(QueryCompilationContext queryCompilationContext) { return new RelationalShapedQueryCompilingExpressionVisitor( + queryCompilationContext, _entityMaterializerSource, _querySqlGeneratorFactory, _sqlExpressionFactory, - _parameterNameGeneratorFactory, - queryCompilationContext.ContextType, - queryCompilationContext.Logger, - queryCompilationContext.TrackQueryResults, - queryCompilationContext.Async); + _parameterNameGeneratorFactory); } } } diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SelectExpression.cs index 92680ddb76b..e170d8531a0 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SelectExpression.cs +++ b/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SelectExpression.cs @@ -3,12 +3,9 @@ using System; using System.Collections.Generic; -using System.Data.SqlTypes; using System.Linq; using System.Linq.Expressions; using System.Reflection; -using Microsoft.EntityFrameworkCore.Diagnostics; -using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; @@ -34,11 +31,17 @@ private readonly IDictionary Projection => _projection; public IReadOnlyList Tables => _tables; public IReadOnlyList Orderings => _orderings; + public ISet Tags { get; private set; } = new HashSet(); public SqlExpression Predicate { get; private set; } public SqlExpression Limit { get; private set; } public SqlExpression Offset { get; private set; } public bool IsDistinct { get; private set; } + public void ApplyTags(ISet tags) + { + Tags = tags; + } + /// /// Marks this as representing an SQL set operation, such as a UNION. /// For regular SQL SELECT expressions, contains None. diff --git a/src/EFCore/Query/NavigationExpansion/NavigationExpansionExpression.cs b/src/EFCore/Query/NavigationExpansion/NavigationExpansionExpression.cs index 628fa997a23..3ef78ff1a8c 100644 --- a/src/EFCore/Query/NavigationExpansion/NavigationExpansionExpression.cs +++ b/src/EFCore/Query/NavigationExpansion/NavigationExpansionExpression.cs @@ -82,7 +82,6 @@ private NavigationExpansionExpressionState ReplaceNavigationExpansionExpressionS newPendingOrderings, newPendingIncludeChain, State.PendingCardinalityReducingOperator, - State.PendingTags, State.CustomRootMappings, State.MaterializeCollectionNavigation); } diff --git a/src/EFCore/Query/NavigationExpansion/NavigationExpansionExpressionState.cs b/src/EFCore/Query/NavigationExpansion/NavigationExpansionExpressionState.cs index 73d70c29afc..ff83239b93b 100644 --- a/src/EFCore/Query/NavigationExpansion/NavigationExpansionExpressionState.cs +++ b/src/EFCore/Query/NavigationExpansion/NavigationExpansionExpressionState.cs @@ -18,7 +18,6 @@ public NavigationExpansionExpressionState( List<(MethodInfo method, LambdaExpression keySelector)> pendingOrderings, NavigationBindingExpression pendingIncludeChain, MethodInfo pendingCardinalityReducingOperator, - List pendingTags, List> customRootMappings, INavigation materializeCollectionNavigation) { @@ -29,7 +28,6 @@ public NavigationExpansionExpressionState( PendingOrderings = pendingOrderings; PendingIncludeChain = pendingIncludeChain; PendingCardinalityReducingOperator = pendingCardinalityReducingOperator; - PendingTags = pendingTags; CustomRootMappings = customRootMappings; MaterializeCollectionNavigation = materializeCollectionNavigation; } @@ -41,7 +39,6 @@ public NavigationExpansionExpressionState( public virtual List<(MethodInfo method, LambdaExpression keySelector)> PendingOrderings { get; set; } public virtual NavigationBindingExpression PendingIncludeChain { get; set; } public virtual MethodInfo PendingCardinalityReducingOperator { get; set; } - public virtual List PendingTags { get; set; } public virtual List> CustomRootMappings { get; set; } public virtual INavigation MaterializeCollectionNavigation { get; set; } } diff --git a/src/EFCore/Query/NavigationExpansion/NavigationExpansionHelpers.cs b/src/EFCore/Query/NavigationExpansion/NavigationExpansionHelpers.cs index fdb03ca2d5e..1e830dd8df1 100644 --- a/src/EFCore/Query/NavigationExpansion/NavigationExpansionHelpers.cs +++ b/src/EFCore/Query/NavigationExpansion/NavigationExpansionHelpers.cs @@ -48,7 +48,6 @@ public static NavigationExpansionExpression CreateNavigationExpansionRoot( new List<(MethodInfo method, LambdaExpression keySelector)>(), pendingIncludeChain: null, pendingCardinalityReducingOperator: null, - pendingTags: new List(), customRootMappings: new List>(), materializeCollectionNavigation), materializeCollectionNavigation?.ClrType ?? operand.Type); diff --git a/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpandingVisitor.cs b/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpandingVisitor.cs index a8f875c68dd..d330aa239d6 100644 --- a/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpandingVisitor.cs +++ b/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpandingVisitor.cs @@ -74,7 +74,6 @@ private Expression ProcessMemberPushdown( navigationExpansionExpression.State.PendingIncludeChain, // we need to remap cardinality reducing operator since it's source type has now changed navigationExpansionExpression.State.PendingCardinalityReducingOperator.GetGenericMethodDefinition().MakeGenericMethod(newPendingSelector.Type), - navigationExpansionExpression.State.PendingTags, navigationExpansionExpression.State.CustomRootMappings, navigationExpansionExpression.State.MaterializeCollectionNavigation); @@ -160,7 +159,6 @@ private Expression ProcessMemberPushdown( navigationExpansionExpression.State.PendingIncludeChain, // we need to remap cardinality reducing operator since it's source type has now changed navigationExpansionExpression.State.PendingCardinalityReducingOperator.GetGenericMethodDefinition().MakeGenericMethod(combinedKeySelectorBody.Type), - navigationExpansionExpression.State.PendingTags, navigationExpansionExpression.State.CustomRootMappings, materializeCollectionNavigation: null); @@ -200,7 +198,6 @@ private Expression ProcessMemberPushdown( navigationExpansionExpression.State.PendingIncludeChain, // we need to remap cardinality reducing operator since it's source type has now changed navigationExpansionExpression.State.PendingCardinalityReducingOperator.GetGenericMethodDefinition().MakeGenericMethod(boundSelectorBody.Type), - navigationExpansionExpression.State.PendingTags, navigationExpansionExpression.State.CustomRootMappings, navigationExpansionExpression.State.MaterializeCollectionNavigation); @@ -364,7 +361,6 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) navigationExpansionExpression.State.PendingIncludeChain, // we need to remap cardinality reducing operator since it's source type has now changed navigationExpansionExpression.State.PendingCardinalityReducingOperator?.GetGenericMethodDefinition().MakeGenericMethod(navigationKeyAccessExpression.Type), - navigationExpansionExpression.State.PendingTags, navigationExpansionExpression.State.CustomRootMappings, navigationExpansionExpression.State.MaterializeCollectionNavigation); diff --git a/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpandingVisitor_MethodCall.cs b/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpandingVisitor_MethodCall.cs index bd580abbd18..5bcd6b1e706 100644 --- a/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpandingVisitor_MethodCall.cs +++ b/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpandingVisitor_MethodCall.cs @@ -97,9 +97,6 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp case "ThenInclude": return ProcessInclude(methodCallExpression); - case nameof(EntityFrameworkQueryableExtensions.TagWith): - return ProcessWithTag(methodCallExpression); - default: return ProcessUnknownMethod(methodCallExpression); } @@ -164,7 +161,6 @@ private NavigationExpansionExpression VisitSourceExpression(Expression sourceExp new List<(MethodInfo method, LambdaExpression keySelector)>(), pendingIncludeChain: null, pendingCardinalityReducingOperator: null, - pendingTags: new List(), new List> { customRootMapping }, materializeCollectionNavigation: null); @@ -411,12 +407,9 @@ private NavigationExpansionExpressionState CreateSelectManyInnerState(Navigation pendingOrderings: new List<(MethodInfo method, LambdaExpression keySelector)>(), pendingIncludeChain: null, pendingCardinalityReducingOperator: null, - pendingTags: collectionSelectorState.PendingTags.ToList(), customRootMappings: customRootMappingMapping.Values.ToList(), materializeCollectionNavigation: null); - collectionSelectorState.PendingTags.Clear(); - return groupingState; } @@ -634,7 +627,6 @@ private Expression ProcessGroupJoin(MethodCallExpression methodCallExpression) outerApplyOrderingsResult.state.PendingOrderings, outerApplyOrderingsResult.state.PendingIncludeChain, outerApplyOrderingsResult.state.PendingCardinalityReducingOperator, - outerApplyOrderingsResult.state.PendingTags, outerApplyOrderingsResult.state.CustomRootMappings.Concat(new[] { groupingMapping }).ToList(), materializeCollectionNavigation: null); @@ -918,7 +910,6 @@ private Expression ProcessSkipTake(MethodCallExpression methodCallExpression) new List<(MethodInfo method, LambdaExpression keySelector)>(), pendingIncludeChain: null, pendingCardinalityReducingOperator: null, - pendingTags: new List(), new List> { customRootMapping }, materializeCollectionNavigation: null); @@ -1252,15 +1243,6 @@ private Expression ProcessFromSql(MethodCallExpression methodCallExpression) return new NavigationExpansionExpression(methodCallExpression, source.State, methodCallExpression.Type); } - private Expression ProcessWithTag(MethodCallExpression methodCallExpression) - { - var source = VisitSourceExpression(methodCallExpression.Arguments[0]); - var tag = (string)((ConstantExpression)methodCallExpression.Arguments[1]).Value; - source.State.PendingTags.Add(tag); - - return source; - } - protected override Expression VisitConstant(ConstantExpression constantExpression) { if (constantExpression.Value != null @@ -1353,7 +1335,6 @@ protected override Expression VisitConstant(ConstantExpression constantExpressio state.PendingOrderings, state.PendingIncludeChain, state.PendingCardinalityReducingOperator, - state.PendingTags, state.CustomRootMappings, state.MaterializeCollectionNavigation); @@ -1431,7 +1412,6 @@ protected override Expression VisitConstant(ConstantExpression constantExpressio new List<(MethodInfo method, LambdaExpression keySelector)>(), pendingIncludeChain: null, pendingCardinalityReducingOperator: null, - outerState.PendingTags.Concat(innerState.PendingTags).ToList(), outerState.CustomRootMappings.Concat(innerState.CustomRootMappings).ToList(), materializeCollectionNavigation: null); diff --git a/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpansionReducingVisitor.cs b/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpansionReducingVisitor.cs index 0026f24c2f0..828d4ccc9c9 100644 --- a/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpansionReducingVisitor.cs +++ b/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpansionReducingVisitor.cs @@ -36,7 +36,6 @@ protected override Expression VisitExtension(Expression extensionExpression) if (!state.ApplyPendingSelector && state.PendingOrderings.Count == 0 - && state.PendingTags.Count == 0 && state.PendingCardinalityReducingOperator == null && state.MaterializeCollectionNavigation == null) { @@ -67,15 +66,6 @@ protected override Expression VisitExtension(Expression extensionExpression) parameter = Expression.Parameter(result.Type.GetSequenceType()); } - if (state.PendingTags.Count > 0) - { - var withTagMethodInfo = EntityFrameworkQueryableExtensions.TagWithMethodInfo.MakeGenericMethod(parameter.Type); - foreach (var pendingTag in state.PendingTags) - { - result = Expression.Call(withTagMethodInfo, result, Expression.Constant(pendingTag)); - } - } - if (state.PendingCardinalityReducingOperator != null) { result = Expression.Call(state.PendingCardinalityReducingOperator, result); @@ -152,7 +142,6 @@ protected override Expression VisitExtension(Expression extensionExpression) navigationExpansionExpression.State.PendingOrderings, navigationExpansionExpression.State.PendingIncludeChain, navigationExpansionExpression.State.PendingCardinalityReducingOperator, - navigationExpansionExpression.State.PendingTags, navigationExpansionExpression.State.CustomRootMappings, navigationExpansionExpression.State.MaterializeCollectionNavigation); diff --git a/src/EFCore/Query/Pipeline/QueryCompilationContext.cs b/src/EFCore/Query/Pipeline/QueryCompilationContext.cs index 067076c4481..0d2f34eb960 100644 --- a/src/EFCore/Query/Pipeline/QueryCompilationContext.cs +++ b/src/EFCore/Query/Pipeline/QueryCompilationContext.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.Expressions; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; @@ -48,9 +49,15 @@ public QueryCompilationContext( public IModel Model { get; } public IDbContextOptions ContextOptions { get; } public bool TrackQueryResults { get; internal set; } + public ISet Tags { get; } = new HashSet(); public virtual IDiagnosticsLogger Logger { get; } public virtual Type ContextType { get; } + public virtual void AddTag(string tag) + { + Tags.Add(tag); + } + public virtual Func CreateQueryExecutor(Expression query) { query = _queryOptimizerFactory.Create(this).Visit(query); diff --git a/src/EFCore/Query/Pipeline/QueryMetadataExtractingExpressionVisitor.cs b/src/EFCore/Query/Pipeline/QueryMetadataExtractingExpressionVisitor.cs index 56210bc880c..94833f8b633 100644 --- a/src/EFCore/Query/Pipeline/QueryMetadataExtractingExpressionVisitor.cs +++ b/src/EFCore/Query/Pipeline/QueryMetadataExtractingExpressionVisitor.cs @@ -20,6 +20,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp if (method.DeclaringType == typeof(EntityFrameworkQueryableExtensions) && method.IsGenericMethod) { + // We visit innerQueryable first so that we can get information in the same order operators are applied. var genericMethodDefinition = method.GetGenericMethodDefinition(); if (genericMethodDefinition == EntityFrameworkQueryableExtensions.AsTrackingMethodInfo || genericMethodDefinition == EntityFrameworkQueryableExtensions.AsNoTrackingMethodInfo) @@ -30,6 +31,14 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp return innerQueryable; } + + if (genericMethodDefinition == EntityFrameworkQueryableExtensions.TagWithMethodInfo) + { + var innerQueryable = Visit(methodCallExpression.Arguments[0]); + _queryCompilationContext.AddTag((string)((ConstantExpression)methodCallExpression.Arguments[1]).Value); + + return innerQueryable; + } } return base.VisitMethodCall(methodCallExpression); diff --git a/src/EFCore/Query/Pipeline/QueryOptimizingExpressionVisitor.cs b/src/EFCore/Query/Pipeline/QueryOptimizingExpressionVisitor.cs index df95a96b8fa..ee245275c6a 100644 --- a/src/EFCore/Query/Pipeline/QueryOptimizingExpressionVisitor.cs +++ b/src/EFCore/Query/Pipeline/QueryOptimizingExpressionVisitor.cs @@ -19,13 +19,13 @@ public QueryOptimizer(QueryCompilationContext queryCompilationContext) public Expression Visit(Expression query) { + query = new QueryMetadataExtractingExpressionVisitor(_queryCompilationContext).Visit(query); query = new AllAnyToContainsRewritingExpressionVisitor().Visit(query); query = new GroupJoinFlatteningExpressionVisitor().Visit(query); query = new NullCheckRemovingExpressionVisitor().Visit(query); query = new EntityEqualityRewritingExpressionVisitor(_queryCompilationContext).Rewrite(query); query = new NavigationExpander(_queryCompilationContext.Model).ExpandNavigations(query); query = new EnumerableToQueryableReMappingExpressionVisitor().Visit(query); - query = new QueryMetadataExtractingExpressionVisitor(_queryCompilationContext).Visit(query); query = new NullCheckRemovingExpressionVisitor().Visit(query); query = new FunctionPreprocessingVisitor().Visit(query); new EnumerableVerifyingExpressionVisitor().Visit(query); diff --git a/src/EFCore/Query/Pipeline/ShapedQueryExpressionVisitor.cs b/src/EFCore/Query/Pipeline/ShapedQueryExpressionVisitor.cs index 2e6e25e2019..9a71327ce19 100644 --- a/src/EFCore/Query/Pipeline/ShapedQueryExpressionVisitor.cs +++ b/src/EFCore/Query/Pipeline/ShapedQueryExpressionVisitor.cs @@ -34,14 +34,16 @@ private static readonly PropertyInfo _cancellationTokenMemberInfo private readonly Expression _cancellationTokenParameter; private readonly EntityMaterializerInjectingExpressionVisitor _entityMaterializerInjectingExpressionVisitor; - public ShapedQueryCompilingExpressionVisitor(IEntityMaterializerSource entityMaterializerSource, bool trackQueryResults, bool async) + public ShapedQueryCompilingExpressionVisitor( + QueryCompilationContext queryCompilationContext, + IEntityMaterializerSource entityMaterializerSource) { _entityMaterializerSource = entityMaterializerSource; - TrackQueryResults = trackQueryResults; + TrackQueryResults = queryCompilationContext.TrackQueryResults; _entityMaterializerInjectingExpressionVisitor = - new EntityMaterializerInjectingExpressionVisitor(entityMaterializerSource, trackQueryResults); - Async = async; - if (async) + new EntityMaterializerInjectingExpressionVisitor(entityMaterializerSource, TrackQueryResults); + Async = queryCompilationContext.Async; + if (Async) { _cancellationTokenParameter = Expression.MakeMemberAccess( QueryCompilationContext.QueryContextParameter, diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/QueryTaggingSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/QueryTaggingSqlServerTest.cs index c16d1f58891..65068922c7a 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/QueryTaggingSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/QueryTaggingSqlServerTest.cs @@ -6,7 +6,7 @@ namespace Microsoft.EntityFrameworkCore.Query { - internal class QueryTaggingSqlServerTest : QueryTaggingTestBase> + public class QueryTaggingSqlServerTest : QueryTaggingTestBase> { public QueryTaggingSqlServerTest( NorthwindQuerySqlServerFixture fixture, ITestOutputHelper testOutputHelper) @@ -51,14 +51,17 @@ public override void Tags_on_subquery() -- Laurel -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] +SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region] +FROM ( + 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] + WHERE [c].[CustomerID] = N'ALFKI' +) AS [t] CROSS JOIN ( - SELECT TOP(5) [o].* + SELECT TOP(5) [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] FROM [Orders] AS [o] ORDER BY [o].[OrderID] -) AS [t] -WHERE [c].[CustomerID] = N'ALFKI'"); +) AS [t0]"); } public override void Duplicate_tags() @@ -80,20 +83,14 @@ public override void Tag_on_include_query() AssertSql( @"-- Yanni -SELECT TOP(1) [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] -ORDER BY [c].[CustomerID]", - // - @"-- Yanni - -SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT TOP(1) [c0].[CustomerID] - FROM [Customers] AS [c0] - ORDER BY [c0].[CustomerID] -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] -ORDER BY [t].[CustomerID]"); +SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] +FROM ( + SELECT TOP(1) [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] + ORDER BY [c].[CustomerID] +) AS [t] +LEFT JOIN [Orders] AS [o] ON [t].[CustomerID] = [o].[CustomerID] +ORDER BY [t].[CustomerID], [o].[OrderID]"); } public override void Tag_on_scalar_query() diff --git a/test/EFCore.SqlServer.FunctionalTests/SqlServerComplianceTest.cs b/test/EFCore.SqlServer.FunctionalTests/SqlServerComplianceTest.cs index b7aa80e203b..e502a3fe32c 100644 --- a/test/EFCore.SqlServer.FunctionalTests/SqlServerComplianceTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/SqlServerComplianceTest.cs @@ -24,7 +24,6 @@ public class SqlServerComplianceTest : RelationalComplianceTestBase typeof(InheritanceRelationshipsQueryTestBase<>), typeof(QueryNavigationsTestBase<>), typeof(ConcurrencyDetectorRelationalTestBase<>), - typeof(QueryTaggingTestBase<>), typeof(GearsOfWarFromSqlQueryTestBase<>), typeof(QueryNoClientEvalTestBase<>), typeof(WarningsTestBase<>), From 81aefa7b52d207c6c6d8d83ec421fe3b15405a36 Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Sun, 30 Jun 2019 19:41:03 -0700 Subject: [PATCH 3/3] Cleanup in navigation expansion --- .../NavigationExpandingVisitor_MethodCall.cs | 28 ------------------- .../Query/SimpleQueryTestBase.cs | 2 +- 2 files changed, 1 insertion(+), 29 deletions(-) diff --git a/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpandingVisitor_MethodCall.cs b/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpandingVisitor_MethodCall.cs index 5bcd6b1e706..fa633a0e870 100644 --- a/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpandingVisitor_MethodCall.cs +++ b/src/EFCore/Query/NavigationExpansion/Visitors/NavigationExpandingVisitor_MethodCall.cs @@ -167,23 +167,10 @@ private NavigationExpansionExpression VisitSourceExpression(Expression sourceExp return new NavigationExpansionExpression(result, state, result.Type); } - private void AdjustCurrentParameterName( - NavigationExpansionExpressionState state, - string newParameterName) - { - if (state.CurrentParameter.Name == null && newParameterName != null) - { - var newParameter = Expression.Parameter(state.CurrentParameter.Type, newParameterName); - state.PendingSelector = (LambdaExpression)new ExpressionReplacingVisitor(state.CurrentParameter, newParameter).Visit(state.PendingSelector); - state.CurrentParameter = newParameter; - } - } - private Expression ProcessWhere(MethodCallExpression methodCallExpression) { var source = VisitSourceExpression(methodCallExpression.Arguments[0]); var predicate = methodCallExpression.Arguments[1].UnwrapLambdaFromQuote(); - AdjustCurrentParameterName(source.State, predicate.Parameters[0].Name); var appliedNavigationsResult = FindAndApplyNavigations(source.Operand, predicate, source.State); var newPredicateBody = new NavigationPropertyUnbindingVisitor(appliedNavigationsResult.state.CurrentParameter).Visit(appliedNavigationsResult.lambdaBody); @@ -203,7 +190,6 @@ private Expression ProcessSelect(MethodCallExpression methodCallExpression) { var source = VisitSourceExpression(methodCallExpression.Arguments[0]); var selector = methodCallExpression.Arguments[1].UnwrapLambdaFromQuote(); - AdjustCurrentParameterName(source.State, selector.Parameters[0].Name); return ProcessSelectCore(source.Operand, source.State, selector, methodCallExpression.Type); } @@ -242,7 +228,6 @@ private Expression ProcessOrderBy(MethodCallExpression methodCallExpression) { var source = VisitSourceExpression(methodCallExpression.Arguments[0]); var keySelector = methodCallExpression.Arguments[1].UnwrapLambdaFromQuote(); - AdjustCurrentParameterName(source.State, keySelector.Parameters[0].Name); var appliedNavigationsResult = FindAndApplyNavigations(source.Operand, keySelector, source.State); var pendingOrdering = (method: methodCallExpression.Method.GetGenericMethodDefinition(), keySelector: Expression.Lambda(appliedNavigationsResult.lambdaBody, appliedNavigationsResult.state.CurrentParameter)); @@ -260,7 +245,6 @@ private Expression ProcessThenByBy(MethodCallExpression methodCallExpression) { var source = VisitSourceExpression(methodCallExpression.Arguments[0]); var keySelector = methodCallExpression.Arguments[1].UnwrapLambdaFromQuote(); - AdjustCurrentParameterName(source.State, keySelector.Parameters[0].Name); var appliedNavigationsResult = FindAndApplyNavigations(source.Operand, keySelector, source.State); @@ -277,7 +261,6 @@ private Expression ProcessSelectMany(MethodCallExpression methodCallExpression) { var outerSourceNee = VisitSourceExpression(methodCallExpression.Arguments[0]); var collectionSelector = methodCallExpression.Arguments[1].UnwrapLambdaFromQuote(); - AdjustCurrentParameterName(outerSourceNee.State, collectionSelector.Parameters[0].Name); var applyNavigationsResult = FindAndApplyNavigations(outerSourceNee.Operand, collectionSelector, outerSourceNee.State); var applyOrderingsResult = ApplyPendingOrderings(applyNavigationsResult.source, applyNavigationsResult.state); @@ -515,9 +498,6 @@ private Expression ProcessJoin(MethodCallExpression methodCallExpression) var innerKeySelector = methodCallExpression.Arguments[3].UnwrapLambdaFromQuote(); var resultSelector = methodCallExpression.Arguments[4].UnwrapLambdaFromQuote(); - AdjustCurrentParameterName(outerSource.State, outerKeySelector.Parameters[0].Name); - AdjustCurrentParameterName(innerSource.State, innerKeySelector.Parameters[0].Name); - var outerApplyNavigationsResult = FindAndApplyNavigations(outerSource.Operand, outerKeySelector, outerSource.State); var innerApplyNavigationsResult = FindAndApplyNavigations(innerSource.Operand, innerKeySelector, innerSource.State); @@ -564,9 +544,6 @@ private Expression ProcessGroupJoin(MethodCallExpression methodCallExpression) var innerKeySelector = methodCallExpression.Arguments[3].UnwrapLambdaFromQuote(); var resultSelector = methodCallExpression.Arguments[4].UnwrapLambdaFromQuote(); - AdjustCurrentParameterName(outerSource.State, outerKeySelector.Parameters[0].Name); - AdjustCurrentParameterName(innerSource.State, innerKeySelector.Parameters[0].Name); - var outerApplyNavigationsResult = FindAndApplyNavigations(outerSource.Operand, outerKeySelector, outerSource.State); var innerApplyNavigationsResult = FindAndApplyNavigations(innerSource.Operand, innerKeySelector, innerSource.State); @@ -672,7 +649,6 @@ private Expression ProcessAll(MethodCallExpression methodCallExpression) var source = VisitSourceExpression(methodCallExpression.Arguments[0]); source = RemoveIncludesFromSource(source); var predicate = methodCallExpression.Arguments[1].UnwrapLambdaFromQuote(); - AdjustCurrentParameterName(source.State, predicate.Parameters[0].Name); var applyNavigationsResult = FindAndApplyNavigations(source.Operand, predicate, source.State); var newPredicateBody = new NavigationPropertyUnbindingVisitor(applyNavigationsResult.state.CurrentParameter).Visit(applyNavigationsResult.lambdaBody); @@ -747,7 +723,6 @@ private Expression ProcessAverageSumMinMax(MethodCallExpression methodCallExpres if (methodCallExpression.Arguments.Count == 2) { var selector = methodCallExpression.Arguments[1].UnwrapLambdaFromQuote(); - AdjustCurrentParameterName(source.State, selector.Parameters[0].Name); var applyNavigationsResult = FindAndApplyNavigations(source.Operand, selector, source.State); var newSelectorBody = new NavigationPropertyUnbindingVisitor(applyNavigationsResult.state.CurrentParameter).Visit(applyNavigationsResult.lambdaBody); var newSelector = Expression.Lambda(newSelectorBody, applyNavigationsResult.state.CurrentParameter); @@ -1083,10 +1058,7 @@ private Expression ProcessInclude(MethodCallExpression methodCallExpression) methodCallExpression = TryConvertToLambdaInclude(methodCallExpression); var source = VisitSourceExpression(methodCallExpression.Arguments[0]); - var includeLambda = methodCallExpression.Arguments[1].UnwrapLambdaFromQuote(); - AdjustCurrentParameterName(source.State, includeLambda.Parameters[0].Name); - var applyOrderingsResult = ApplyPendingOrderings(source.Operand, source.State); // just bind to mark all the necessary navigation for include in the future diff --git a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs index 372f8a06424..d594a0ff068 100644 --- a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs @@ -5428,7 +5428,7 @@ orderby c.CustomerID select c.CustomerID); } - [ConditionalTheory] + [ConditionalTheory(Skip = "Issue#16365")] [MemberData(nameof(IsAsyncData))] public virtual Task Comparing_navigations_using_Equals(bool isAsync) {