diff --git a/src/EFCore.Relational/Query/CollectionResultExpression.cs b/src/EFCore.Relational/Query/CollectionResultExpression.cs new file mode 100644 index 00000000000..72432446c5f --- /dev/null +++ b/src/EFCore.Relational/Query/CollectionResultExpression.cs @@ -0,0 +1,99 @@ +// 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 Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Utilities; + +namespace Microsoft.EntityFrameworkCore.Query +{ + /// + /// + /// An expression that represents creation of a collection in for relational providers. + /// + /// + /// This type is typically used by database providers (and other extensions). It is generally + /// not used in application code. + /// + /// + public class CollectionResultExpression : Expression, IPrintableExpression + { + /// + /// Creates a new instance of the class. + /// + /// An expression reprensenting how to get the subquery from SelectExpression to get the elements. + /// A navigation associated with this collection, if any. + /// The clr type of individual elements in the collection. + public CollectionResultExpression( + ProjectionBindingExpression projectionBindingExpression, + INavigationBase? navigation, + Type elementType) + { + ProjectionBindingExpression = projectionBindingExpression; + Navigation = navigation; + ElementType = elementType; + } + + /// + /// The expression to get the subquery for this collection. + /// + public virtual ProjectionBindingExpression ProjectionBindingExpression { get; } + /// + /// The navigation if associated with the collection. + /// + public virtual INavigationBase? Navigation { get; } + /// + /// The clr type of elements of the collection. + /// + public virtual Type ElementType { get; } + + /// + public override Type Type => ProjectionBindingExpression.Type; + /// + public override ExpressionType NodeType => ExpressionType.Extension; + + /// + protected override Expression VisitChildren(ExpressionVisitor visitor) + { + Check.NotNull(visitor, nameof(visitor)); + + var projectionBindingExpression = (ProjectionBindingExpression)visitor.Visit(ProjectionBindingExpression); + + return Update(projectionBindingExpression); + } + + /// + /// Creates a new expression that is like this one, but using the supplied children. If all of the children are the same, it will + /// return this expression. + /// + /// The property of the result. + /// This expression if no children changed, or an expression with the updated children. + public virtual CollectionResultExpression Update(ProjectionBindingExpression projectionBindingExpression) + { + Check.NotNull(projectionBindingExpression, nameof(projectionBindingExpression)); + + return projectionBindingExpression != ProjectionBindingExpression + ? new CollectionResultExpression(projectionBindingExpression, Navigation, ElementType) + : this; + } + + /// + public virtual void Print(ExpressionPrinter expressionPrinter) + { + expressionPrinter.AppendLine("CollectionResultExpression:"); + using (expressionPrinter.Indent()) + { + expressionPrinter.Append("ProjectionBindingExpression:"); + expressionPrinter.Visit(ProjectionBindingExpression); + expressionPrinter.AppendLine(); + if (Navigation != null) + { + expressionPrinter.Append("Navigation:").AppendLine(Navigation.ToString()!); + } + expressionPrinter.Append("ElementType:").AppendLine(ElementType.ShortDisplayName()); + } + } + } +} diff --git a/src/EFCore.Relational/Query/EntityProjectionExpression.cs b/src/EFCore.Relational/Query/EntityProjectionExpression.cs index 3f098ced243..3fc7d9c8480 100644 --- a/src/EFCore.Relational/Query/EntityProjectionExpression.cs +++ b/src/EFCore.Relational/Query/EntityProjectionExpression.cs @@ -216,5 +216,8 @@ public virtual void AddNavigationBinding(INavigation navigation, EntityShaperExp ? expression : null; } + + /// + public override string ToString() => $"EntityProjectionExpression: {EntityType.ShortName()}"; } } diff --git a/src/EFCore.Relational/Query/Internal/CollectionJoinApplyingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/CollectionJoinApplyingExpressionVisitor.cs deleted file mode 100644 index d9947f5f66b..00000000000 --- a/src/EFCore.Relational/Query/Internal/CollectionJoinApplyingExpressionVisitor.cs +++ /dev/null @@ -1,99 +0,0 @@ -// 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 Microsoft.EntityFrameworkCore.Diagnostics; -using Microsoft.EntityFrameworkCore.Query.SqlExpressions; -using Microsoft.EntityFrameworkCore.Utilities; - -namespace Microsoft.EntityFrameworkCore.Query.Internal -{ - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public class CollectionJoinApplyingExpressionVisitor : ExpressionVisitor - { - private readonly bool _splitQuery; - private readonly bool _noConfiguredBehavior; - private readonly IDiagnosticsLogger _logger; - private int _collectionId; - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public CollectionJoinApplyingExpressionVisitor(RelationalQueryCompilationContext queryCompilationContext) - { - Check.NotNull(queryCompilationContext, nameof(queryCompilationContext)); - - _splitQuery = queryCompilationContext.QuerySplittingBehavior == QuerySplittingBehavior.SplitQuery; - _noConfiguredBehavior = queryCompilationContext.QuerySplittingBehavior == null; - _logger = queryCompilationContext.Logger; - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - protected override Expression VisitExtension(Expression extensionExpression) - { - Check.NotNull(extensionExpression, nameof(extensionExpression)); - - if (extensionExpression is CollectionShaperExpression collectionShaperExpression) - { - var collectionId = _collectionId++; - - if (_noConfiguredBehavior - && _collectionId == 2) - { - _logger.MultipleCollectionIncludeWarning(); - } - - var projectionBindingExpression = (ProjectionBindingExpression)collectionShaperExpression.Projection; - var selectExpression = (SelectExpression)projectionBindingExpression.QueryExpression; - // Do pushdown beforehand so it updates all pending collections first - if (selectExpression.IsDistinct - || selectExpression.Limit != null - || selectExpression.Offset != null - || selectExpression.GroupBy.Count > 0) - { - selectExpression.PushdownIntoSubquery(); - } - - var innerShaper = Visit(collectionShaperExpression.InnerShaper); - - var collectionJoin = selectExpression.ApplyCollectionJoin( - projectionBindingExpression.Index!.Value, - collectionId, - innerShaper, - collectionShaperExpression.Navigation, - collectionShaperExpression.ElementType, - _splitQuery); - - if (_splitQuery - && collectionJoin == null) - { - throw new InvalidOperationException( - RelationalStrings.UnableToSplitCollectionProjectionInSplitQuery( - $"{nameof(QuerySplittingBehavior)}.{QuerySplittingBehavior.SplitQuery}", - nameof(RelationalQueryableExtensions.AsSplitQuery), - nameof(RelationalQueryableExtensions.AsSingleQuery))); - } - - return collectionJoin!; - } - - return extensionExpression is ShapedQueryExpression shapedQueryExpression - ? shapedQueryExpression.UpdateShaperExpression(Visit(shapedQueryExpression.ShaperExpression)) - : base.VisitExtension(extensionExpression); - } - } -} diff --git a/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs index 0fe1df633c7..0ed2fbfbd31 100644 --- a/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/RelationalProjectionBindingExpressionVisitor.cs @@ -10,7 +10,6 @@ using System.Reflection; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; -using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; @@ -33,9 +32,10 @@ private static readonly MethodInfo _getParameterValueMethodInfo private readonly IncludeFindingExpressionVisitor _includeFindingExpressionVisitor; private SelectExpression _selectExpression; - private SqlExpression[] _existingProjections; - private bool _clientEval; + + private bool _indexBasedBinding; private Dictionary? _entityProjectionCache; + private List? _clientProjections; private readonly Dictionary _projectionMapping = new(); private readonly Stack _projectionMembers = new(); @@ -54,7 +54,6 @@ public RelationalProjectionBindingExpressionVisitor( _sqlTranslator = sqlTranslatingExpressionVisitor; _includeFindingExpressionVisitor = new IncludeFindingExpressionVisitor(); _selectExpression = null!; - _existingProjections = Array.Empty(); } /// @@ -66,7 +65,7 @@ public RelationalProjectionBindingExpressionVisitor( public virtual Expression Translate(SelectExpression selectExpression, Expression expression) { _selectExpression = selectExpression; - _clientEval = false; + _indexBasedBinding = false; _projectionMembers.Push(new ProjectionMember()); @@ -75,21 +74,25 @@ public virtual Expression Translate(SelectExpression selectExpression, Expressio if (result == QueryCompilationContext.NotTranslatedExpression) { - _clientEval = true; + _indexBasedBinding = true; _entityProjectionCache = new(); + _projectionMapping.Clear(); + _clientProjections = new List(); expandedExpression = _queryableMethodTranslatingExpressionVisitor.ExpandWeakEntities(_selectExpression, expression); - _existingProjections = _selectExpression.Projection.Select(e => e.Expression).ToArray(); - _selectExpression.ClearProjection(); result = Visit(expandedExpression); + _selectExpression.ReplaceProjection(_clientProjections); + _clientProjections.Clear(); + } + else + { + _selectExpression.ReplaceProjection(_projectionMapping); _projectionMapping.Clear(); } - _selectExpression.ReplaceProjectionMapping(_projectionMapping); _selectExpression = null!; _projectionMembers.Clear(); - _projectionMapping.Clear(); result = MatchTypes(result!, expression.Type); @@ -123,66 +126,60 @@ public virtual Expression Translate(SelectExpression selectExpression, Expressio return parameter; } - if (_clientEval) + if (_indexBasedBinding) { switch (expression) { case ConstantExpression _: return expression; + case ParameterExpression parameterExpression: + return parameterExpression.Name?.StartsWith(QueryCompilationContext.QueryParameterPrefix, StringComparison.Ordinal) + == true + ? Expression.Call( + _getParameterValueMethodInfo.MakeGenericMethod(parameterExpression.Type), + QueryCompilationContext.QueryContextParameter, + Expression.Constant(parameterExpression.Name)) + : throw new InvalidOperationException(CoreStrings.TranslationFailed(parameterExpression.Print())); + case ProjectionBindingExpression projectionBindingExpression: - if (projectionBindingExpression.Index is int index) + var mappedProjection = _selectExpression.GetProjection(projectionBindingExpression); + if (mappedProjection is EntityProjectionExpression entityProjection) { - var newIndex = _selectExpression.AddToProjection(_existingProjections[index]); - - return new ProjectionBindingExpression(_selectExpression, newIndex, expression.Type); + return AddClientProjection(entityProjection, typeof(ValueBuffer)); } - if (projectionBindingExpression.ProjectionMember != null) + if (mappedProjection is SqlExpression mappedSqlExpression) { - // This would be SqlExpression. EntityProjectionExpression would be wrapped inside EntityShaperExpression. - var mappedProjection = (SqlExpression)((SelectExpression)projectionBindingExpression.QueryExpression) - .GetMappedProjection(projectionBindingExpression.ProjectionMember); - - return new ProjectionBindingExpression( - _selectExpression, _selectExpression.AddToProjection(mappedProjection), expression.Type); + return AddClientProjection(mappedSqlExpression, expression.Type.MakeNullable()); } throw new InvalidOperationException(CoreStrings.TranslationFailed(projectionBindingExpression.Print())); - case ParameterExpression parameterExpression: - if (parameterExpression.Name?.StartsWith(QueryCompilationContext.QueryParameterPrefix, StringComparison.Ordinal) - == true) - { - return Expression.Call( - _getParameterValueMethodInfo.MakeGenericMethod(parameterExpression.Type), - QueryCompilationContext.QueryContextParameter, - Expression.Constant(parameterExpression.Name)); - } - - throw new InvalidOperationException(CoreStrings.TranslationFailed(parameterExpression.Print())); - case MaterializeCollectionNavigationExpression materializeCollectionNavigationExpression: - return _selectExpression.AddCollectionProjection( - _queryableMethodTranslatingExpressionVisitor.TranslateSubquery( - materializeCollectionNavigationExpression.Subquery)!, + _clientProjections!.Add(_queryableMethodTranslatingExpressionVisitor.TranslateSubquery( + materializeCollectionNavigationExpression.Subquery)!); + return new CollectionResultExpression( + new ProjectionBindingExpression(_selectExpression, _clientProjections.Count - 1, expression.Type), materializeCollectionNavigationExpression.Navigation, materializeCollectionNavigationExpression.Navigation.ClrType.GetSequenceType()); case MethodCallExpression methodCallExpression: - { if (methodCallExpression.Method.IsGenericMethod && methodCallExpression.Method.DeclaringType == typeof(Enumerable) - && methodCallExpression.Method.Name == nameof(Enumerable.ToList)) + && methodCallExpression.Method.Name == nameof(Enumerable.ToList) + && methodCallExpression.Arguments.Count == 1 + && methodCallExpression.Arguments[0].Type.TryGetElementType(typeof(IQueryable<>)) != null) { - var elementType = methodCallExpression.Method.GetGenericArguments()[0]; - - var result = _queryableMethodTranslatingExpressionVisitor.TranslateSubquery( + var subquery = _queryableMethodTranslatingExpressionVisitor.TranslateSubquery( methodCallExpression.Arguments[0]); - - if (result != null) + if (subquery != null) { - return _selectExpression.AddCollectionProjection(result, null, elementType); + _clientProjections!.Add(subquery); + return new CollectionResultExpression( + new ProjectionBindingExpression(_selectExpression, _clientProjections.Count - 1, expression.Type), + navigation: null, + methodCallExpression.Method.GetGenericArguments()[0]); } } else @@ -190,49 +187,32 @@ public virtual Expression Translate(SelectExpression selectExpression, Expressio var subquery = _queryableMethodTranslatingExpressionVisitor.TranslateSubquery(methodCallExpression); if (subquery != null) { - if (subquery.ResultCardinality == ResultCardinality.Enumerable) - { - return _selectExpression.AddCollectionProjection(subquery, null, subquery.ShaperExpression.Type); - } - - static bool IsAggregateResultWithCustomShaper(MethodInfo method) + // This simplifies the check when subquery is translated and can be lifted as scalar. + var scalarTranslation = _sqlTranslator.Translate(subquery); + if (scalarTranslation != null) { - if (method.IsGenericMethod) - { - method = method.GetGenericMethodDefinition(); - } - - return QueryableMethods.IsAverageWithoutSelector(method) - || QueryableMethods.IsAverageWithSelector(method) - || method == QueryableMethods.MaxWithoutSelector - || method == QueryableMethods.MaxWithSelector - || method == QueryableMethods.MinWithoutSelector - || method == QueryableMethods.MinWithSelector - || QueryableMethods.IsSumWithoutSelector(method) - || QueryableMethods.IsSumWithSelector(method); + return AddClientProjection(scalarTranslation, expression.Type.MakeNullable()); } - if (!(subquery.ShaperExpression is ProjectionBindingExpression - || (subquery.ShaperExpression is UnaryExpression unaryExpression - && unaryExpression.NodeType == ExpressionType.Convert - && unaryExpression.Type.MakeNullable() == unaryExpression.Operand.Type - && unaryExpression.Operand is ProjectionBindingExpression) - || IsAggregateResultWithCustomShaper(methodCallExpression.Method))) - { - return _selectExpression.AddSingleProjection(subquery); - } + _clientProjections!.Add(subquery); + var projectionBindingExpression = new ProjectionBindingExpression( + _selectExpression, _clientProjections.Count - 1, expression.Type); + return subquery.ResultCardinality == ResultCardinality.Enumerable + ? new CollectionResultExpression( + projectionBindingExpression, navigation: null, subquery.ShaperExpression.Type) + : projectionBindingExpression; } } - break; - } } var translation = _sqlTranslator.Translate(expression); - return translation == null - ? base.Visit(expression) - : new ProjectionBindingExpression( - _selectExpression, _selectExpression.AddToProjection(translation), expression.Type.MakeNullable()); + if (translation != null) + { + return AddClientProjection(translation, expression.Type.MakeNullable()); + } + + return base.Visit(expression); } else { @@ -306,38 +286,27 @@ protected override Expression VisitExtension(Expression extensionExpression) EntityProjectionExpression entityProjectionExpression; if (entityShaperExpression.ValueBufferExpression is ProjectionBindingExpression projectionBindingExpression) { - // If projectionBinding is not mapped then SelectExpression has client projection - // Hence force client eval - if (projectionBindingExpression.ProjectionMember == null) + if (projectionBindingExpression.ProjectionMember == null + && !_indexBasedBinding) { - if (_clientEval) - { - var indexMap = new Dictionary(); - foreach (var item in projectionBindingExpression.IndexMap!) - { - indexMap[item.Key] = _selectExpression.AddToProjection(_existingProjections[item.Value]); - } - - return entityShaperExpression.Update(new ProjectionBindingExpression(_selectExpression, indexMap)); - } - + // If projectionBinding is not mapped via projection member then it is bound via index + // Hence we need to switch to index based binding too. return QueryCompilationContext.NotTranslatedExpression; } entityProjectionExpression = (EntityProjectionExpression)((SelectExpression)projectionBindingExpression.QueryExpression) - .GetMappedProjection(projectionBindingExpression.ProjectionMember); + .GetProjection(projectionBindingExpression); } else { entityProjectionExpression = (EntityProjectionExpression)entityShaperExpression.ValueBufferExpression; } - if (_clientEval) + if (_indexBasedBinding) { if (!_entityProjectionCache!.TryGetValue(entityProjectionExpression, out var entityProjectionBinding)) { - entityProjectionBinding = new ProjectionBindingExpression( - _selectExpression, _selectExpression.AddToProjection(entityProjectionExpression)); + entityProjectionBinding = AddClientProjection(entityProjectionExpression, typeof(ValueBuffer)); _entityProjectionCache[entityProjectionExpression] = entityProjectionBinding; } @@ -351,10 +320,25 @@ protected override Expression VisitExtension(Expression extensionExpression) } case IncludeExpression _: - return _clientEval ? base.VisitExtension(extensionExpression) : QueryCompilationContext.NotTranslatedExpression; + return _indexBasedBinding ? base.VisitExtension(extensionExpression) : QueryCompilationContext.NotTranslatedExpression; - case CollectionShaperExpression _: - return _clientEval ? extensionExpression : QueryCompilationContext.NotTranslatedExpression; + case CollectionResultExpression collectionResultExpression: + { + // TODO this should not be needed at some point, we shouldn't be revisit same projection. + // This happens because we don't process result selector for Join/SelectMany directly. + if (_indexBasedBinding) + { + Check.DebugAssert(ReferenceEquals(_selectExpression, collectionResultExpression.ProjectionBindingExpression.QueryExpression), + "The projection should belong to same select expression."); + var mappedProjection = _selectExpression.GetProjection(collectionResultExpression.ProjectionBindingExpression); + _clientProjections!.Add(mappedProjection); + + return collectionResultExpression.Update( + new ProjectionBindingExpression(_selectExpression, _clientProjections.Count - 1, collectionResultExpression.Type)); + } + + return QueryCompilationContext.NotTranslatedExpression; + } default: throw new InvalidOperationException(CoreStrings.TranslationFailed(extensionExpression.Print())); @@ -410,7 +394,7 @@ protected override MemberAssignment VisitMemberAssignment(MemberAssignment membe { var expression = memberAssignment.Expression; Expression? visitedExpression; - if (_clientEval) + if (_indexBasedBinding) { visitedExpression = Visit(memberAssignment.Expression); } @@ -524,7 +508,7 @@ protected override Expression VisitNew(NewExpression newExpression) return newExpression; } - if (!_clientEval + if (!_indexBasedBinding && newExpression.Members == null) { return QueryCompilationContext.NotTranslatedExpression; @@ -535,7 +519,7 @@ protected override Expression VisitNew(NewExpression newExpression) { var argument = newExpression.Arguments[i]; Expression? visitedArgument; - if (_clientEval) + if (_indexBasedBinding) { visitedArgument = Visit(argument); } @@ -598,6 +582,18 @@ private static Expression MatchTypes(Expression expression, Type targetType) return expression; } + private ProjectionBindingExpression AddClientProjection(Expression expression, Type type) + { + var existingIndex = _clientProjections!.FindIndex(e => e.Equals(expression)); + if (existingIndex == -1) + { + _clientProjections.Add(expression); + existingIndex = _clientProjections.Count - 1; + } + + return new ProjectionBindingExpression(_selectExpression, existingIndex, type); + } + #pragma warning disable IDE0052 // Remove unread private members private static T GetParameterValue(QueryContext queryContext, string parameterName) #pragma warning restore IDE0052 // Remove unread private members diff --git a/src/EFCore.Relational/Query/Internal/SelectExpressionProjectionApplyingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/SelectExpressionProjectionApplyingExpressionVisitor.cs index e80aa3f2f29..4c3b5f1079f 100644 --- a/src/EFCore.Relational/Query/Internal/SelectExpressionProjectionApplyingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Internal/SelectExpressionProjectionApplyingExpressionVisitor.cs @@ -15,6 +15,19 @@ namespace Microsoft.EntityFrameworkCore.Query.Internal /// public class SelectExpressionProjectionApplyingExpressionVisitor : ExpressionVisitor { + private readonly QuerySplittingBehavior _querySplittingBehavior; + + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + public SelectExpressionProjectionApplyingExpressionVisitor(QuerySplittingBehavior? querySplittingBehavior) + { + _querySplittingBehavior = querySplittingBehavior ?? QuerySplittingBehavior.SingleQuery; + } + /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in @@ -25,18 +38,12 @@ protected override Expression VisitExtension(Expression extensionExpression) { Check.NotNull(extensionExpression, nameof(extensionExpression)); - if (extensionExpression is ShapedQueryExpression shapedQueryExpression) - { - return shapedQueryExpression.Update(Visit(shapedQueryExpression.QueryExpression), shapedQueryExpression.ShaperExpression); - } - - if (extensionExpression is SelectExpression selectExpression) - { - selectExpression.ApplyProjection(); - // We visit base to apply projection to inner SelectExpressions - } - - return base.VisitExtension(extensionExpression); + return extensionExpression is ShapedQueryExpression shapedQueryExpression + && shapedQueryExpression.QueryExpression is SelectExpression selectExpression + ? shapedQueryExpression.Update( + selectExpression, + selectExpression.ApplyProjection(shapedQueryExpression.ShaperExpression, _querySplittingBehavior)) + : base.VisitExtension(extensionExpression); } } } diff --git a/src/EFCore.Relational/Query/RelationalCollectionShaperExpression.cs b/src/EFCore.Relational/Query/RelationalCollectionShaperExpression.cs index a41f0035614..6f77a52913b 100644 --- a/src/EFCore.Relational/Query/RelationalCollectionShaperExpression.cs +++ b/src/EFCore.Relational/Query/RelationalCollectionShaperExpression.cs @@ -60,6 +60,7 @@ public RelationalCollectionShaperExpression( /// An expression used to create individual elements of the collection. /// A navigation associated with this collection, if any. /// The clr type of individual elements in the collection. + [Obsolete("Use ctor without collectionId")] public RelationalCollectionShaperExpression( int collectionId, Expression parentIdentifier, @@ -90,10 +91,51 @@ public RelationalCollectionShaperExpression( ElementType = elementType; } + /// + /// Creates a new instance of the class. + /// + /// An identifier for the parent element. + /// An identifier for the outer element. + /// An identifier for the element in the collection. + /// A list of value comparers to compare parent identifier. + /// A list of value comparers to compare outer identifier. + /// A list of value comparers to compare self identifier. + /// An expression used to create individual elements of the collection. + /// A navigation associated with this collection, if any. + /// The clr type of individual elements in the collection. + public RelationalCollectionShaperExpression( + Expression parentIdentifier, + Expression outerIdentifier, + Expression selfIdentifier, + IReadOnlyList? parentIdentifierValueComparers, + IReadOnlyList? outerIdentifierValueComparers, + IReadOnlyList? selfIdentifierValueComparers, + Expression innerShaper, + INavigationBase? navigation, + Type elementType) + { + Check.NotNull(parentIdentifier, nameof(parentIdentifier)); + Check.NotNull(outerIdentifier, nameof(outerIdentifier)); + Check.NotNull(selfIdentifier, nameof(selfIdentifier)); + Check.NotNull(innerShaper, nameof(innerShaper)); + Check.NotNull(elementType, nameof(elementType)); + + ParentIdentifier = parentIdentifier; + OuterIdentifier = outerIdentifier; + SelfIdentifier = selfIdentifier; + ParentIdentifierValueComparers = parentIdentifierValueComparers; + OuterIdentifierValueComparers = outerIdentifierValueComparers; + SelfIdentifierValueComparers = selfIdentifierValueComparers; + InnerShaper = innerShaper; + Navigation = navigation; + ElementType = elementType; + } + /// /// A unique id for this collection shaper. /// - public virtual int CollectionId { get; } + [Obsolete("CollectionId are not stored in shaper anymore. Shaper compiler assigns it as needed.")] + public virtual int? CollectionId { get; } /// /// The identifier for the parent element. @@ -186,7 +228,7 @@ public virtual RelationalCollectionShaperExpression Update( || selfIdentifier != SelfIdentifier || innerShaper != InnerShaper ? new RelationalCollectionShaperExpression( - CollectionId, parentIdentifier, outerIdentifier, selfIdentifier, + parentIdentifier, outerIdentifier, selfIdentifier, ParentIdentifierValueComparers, OuterIdentifierValueComparers, SelfIdentifierValueComparers, innerShaper, Navigation, ElementType) : this; @@ -200,7 +242,6 @@ void IPrintableExpression.Print(ExpressionPrinter expressionPrinter) expressionPrinter.AppendLine("RelationalCollectionShaper:"); using (expressionPrinter.Indent()) { - expressionPrinter.AppendLine($"CollectionId: {CollectionId}"); expressionPrinter.Append("ParentIdentifier:"); expressionPrinter.Visit(ParentIdentifier); expressionPrinter.AppendLine(); diff --git a/src/EFCore.Relational/Query/RelationalQueryTranslationPostprocessor.cs b/src/EFCore.Relational/Query/RelationalQueryTranslationPostprocessor.cs index 7dfa5916708..b84cc8429b1 100644 --- a/src/EFCore.Relational/Query/RelationalQueryTranslationPostprocessor.cs +++ b/src/EFCore.Relational/Query/RelationalQueryTranslationPostprocessor.cs @@ -46,8 +46,8 @@ public RelationalQueryTranslationPostprocessor( public override Expression Process(Expression query) { query = base.Process(query); - query = new SelectExpressionProjectionApplyingExpressionVisitor().Visit(query); - query = new CollectionJoinApplyingExpressionVisitor((RelationalQueryCompilationContext)QueryCompilationContext).Visit(query); + query = new SelectExpressionProjectionApplyingExpressionVisitor( + ((RelationalQueryCompilationContext)QueryCompilationContext).QuerySplittingBehavior).Visit(query); #if DEBUG // TODO: 24460 blocks from enabling this //query = new TableAliasVerifyingExpressionVisitor().Visit(query); diff --git a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs index 698cc218679..79436458c77 100644 --- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs @@ -196,7 +196,7 @@ private static ShapedQueryExpression CreateShapedQueryExpression(IEntityType ent var selectExpression = (SelectExpression)source.QueryExpression; selectExpression.ApplyPredicate(_sqlExpressionFactory.Not(translation)); - selectExpression.ReplaceProjectionMapping(new Dictionary()); + selectExpression.ReplaceProjection(new Dictionary()); if (selectExpression.Limit == null && selectExpression.Offset == null) { @@ -226,7 +226,7 @@ private static ShapedQueryExpression CreateShapedQueryExpression(IEntityType ent } var selectExpression = (SelectExpression)source.QueryExpression; - selectExpression.ReplaceProjectionMapping(new Dictionary()); + selectExpression.ReplaceProjection(new Dictionary()); if (selectExpression.Limit == null && selectExpression.Offset == null) { @@ -248,32 +248,7 @@ private static ShapedQueryExpression CreateShapedQueryExpression(IEntityType ent Check.NotNull(source, nameof(source)); Check.NotNull(resultType, nameof(resultType)); - var selectExpression = (SelectExpression)source.QueryExpression; - selectExpression.PrepareForAggregate(); - HandleGroupByForAggregate(selectExpression); - - var newSelector = selector == null - || selector.Body == selector.Parameters[0] - ? selectExpression.Projection.Count == 0 - ? selectExpression.GetMappedProjection(new ProjectionMember()) - : null - : RemapLambdaBody(source, selector); - - if (newSelector == null) - { - return null; - } - - var translatedSelector = TranslateExpression(newSelector); - if (translatedSelector == null) - { - return null; - } - - var projection = _sqlTranslator.TranslateAverage(translatedSelector); - return projection != null - ? AggregateResultShaper(source, projection, throwWhenEmpty: true, resultType) - : null; + return TranslateAggregateWithSelector(source, selector, e => _sqlTranslator.TranslateAverage(e), throwWhenEmpty: true, resultType); } /// @@ -318,14 +293,26 @@ private static ShapedQueryExpression CreateShapedQueryExpression(IEntityType ent selectExpression.ClearOrdering(); } - selectExpression.ApplyProjection(); - translation = _sqlExpressionFactory.In(translation, selectExpression, false); + // TODO: See issue #24671 + if (source.ShaperExpression is ProjectionBindingExpression projectionBindingExpression) + { + var projection = selectExpression.GetProjection(projectionBindingExpression); + if (projection is SqlExpression sqlExpression) + { + selectExpression.ReplaceProjection(new List()); + selectExpression.AddToProjection(sqlExpression); - return source.Update( - _sqlExpressionFactory.Select(translation), - Expression.Convert( - new ProjectionBindingExpression(source.QueryExpression, new ProjectionMember(), typeof(bool?)), - typeof(bool))); + translation = _sqlExpressionFactory.In(translation, selectExpression, false); + + return new ShapedQueryExpression( + _sqlExpressionFactory.Select(translation), + Expression.Convert( + new ProjectionBindingExpression(source.QueryExpression, new ProjectionMember(), typeof(bool?)), + typeof(bool))); + } + } + + return null; } /// @@ -357,7 +344,7 @@ private static ShapedQueryExpression CreateShapedQueryExpression(IEntityType ent var projectionMapping = new Dictionary { { new ProjectionMember(), translation } }; selectExpression.ClearOrdering(); - selectExpression.ReplaceProjectionMapping(projectionMapping); + selectExpression.ReplaceProjection(projectionMapping); return source.UpdateShaperExpression( Expression.Convert( @@ -757,7 +744,7 @@ private SqlExpression CreateJoinPredicate(Expression outerKey, Expression innerK var projectionMapping = new Dictionary { { new ProjectionMember(), translation } }; selectExpression.ClearOrdering(); - selectExpression.ReplaceProjectionMapping(projectionMapping); + selectExpression.ReplaceProjection(projectionMapping); return source.UpdateShaperExpression( Expression.Convert( @@ -769,64 +756,18 @@ private SqlExpression CreateJoinPredicate(Expression outerKey, Expression innerK protected override ShapedQueryExpression? TranslateMax(ShapedQueryExpression source, LambdaExpression? selector, Type resultType) { Check.NotNull(source, nameof(source)); + Check.NotNull(resultType, nameof(resultType)); - var selectExpression = (SelectExpression)source.QueryExpression; - selectExpression.PrepareForAggregate(); - HandleGroupByForAggregate(selectExpression); - - var newSelector = selector == null - || selector.Body == selector.Parameters[0] - ? selectExpression.Projection.Count == 0 - ? selectExpression.GetMappedProjection(new ProjectionMember()) - : null - : RemapLambdaBody(source, selector); - - if (newSelector == null) - { - return null; - } - - var translatedSelector = TranslateExpression(newSelector); - if (translatedSelector == null) - { - return null; - } - - var projection = _sqlTranslator.TranslateMax(translatedSelector); - - return AggregateResultShaper(source, projection, throwWhenEmpty: true, resultType); + return TranslateAggregateWithSelector(source, selector, e => _sqlTranslator.TranslateMax(e), throwWhenEmpty: true, resultType); } /// protected override ShapedQueryExpression? TranslateMin(ShapedQueryExpression source, LambdaExpression? selector, Type resultType) { Check.NotNull(source, nameof(source)); + Check.NotNull(resultType, nameof(resultType)); - var selectExpression = (SelectExpression)source.QueryExpression; - selectExpression.PrepareForAggregate(); - HandleGroupByForAggregate(selectExpression); - - var newSelector = selector == null - || selector.Body == selector.Parameters[0] - ? selectExpression.Projection.Count == 0 - ? selectExpression.GetMappedProjection(new ProjectionMember()) - : null - : RemapLambdaBody(source, selector); - - if (newSelector == null) - { - return null; - } - - var translatedSelector = TranslateExpression(newSelector); - if (translatedSelector == null) - { - return null; - } - - var projection = _sqlTranslator.TranslateMin(translatedSelector); - - return AggregateResultShaper(source, projection, throwWhenEmpty: true, resultType); + return TranslateAggregateWithSelector(source, selector, e => _sqlTranslator.TranslateMin(e), throwWhenEmpty: true, resultType); } /// @@ -872,8 +813,8 @@ private SqlExpression CreateJoinPredicate(Expression outerKey, Expression innerK var projectionMember = projectionBindingExpression.ProjectionMember; Check.DebugAssert(new ProjectionMember().Equals(projectionMember), "Invalid ProjectionMember when processing OfType"); - var entityProjectionExpression = (EntityProjectionExpression)selectExpression.GetMappedProjection(projectionMember); - selectExpression.ReplaceProjectionMapping( + var entityProjectionExpression = (EntityProjectionExpression)selectExpression.GetProjection(projectionBindingExpression); + selectExpression.ReplaceProjection( new Dictionary { { projectionMember, entityProjectionExpression.UpdateEntityType(derivedType) } @@ -1120,32 +1061,7 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp Check.NotNull(source, nameof(source)); Check.NotNull(resultType, nameof(resultType)); - var selectExpression = (SelectExpression)source.QueryExpression; - selectExpression.PrepareForAggregate(); - HandleGroupByForAggregate(selectExpression); - - var newSelector = selector == null - || selector.Body == selector.Parameters[0] - ? selectExpression.Projection.Count == 0 - ? selectExpression.GetMappedProjection(new ProjectionMember()) - : null - : RemapLambdaBody(source, selector); - - if (newSelector == null) - { - return null; - } - - var translatedSelector = TranslateExpression(newSelector); - if (translatedSelector == null) - { - return null; - } - - var projection = _sqlTranslator.TranslateSum(translatedSelector); - return projection != null - ? AggregateResultShaper(source, projection, throwWhenEmpty: false, resultType) - : null; + return TranslateAggregateWithSelector(source, selector, e => _sqlTranslator.TranslateSum(e), throwWhenEmpty: false, resultType); } /// @@ -1412,7 +1328,7 @@ outerKey is NewArrayExpression newArrayExpression var entityProjectionExpression = (EntityProjectionExpression) (entityShaperExpression.ValueBufferExpression is ProjectionBindingExpression projectionBindingExpression - ? _selectExpression.GetMappedProjection(projectionBindingExpression.ProjectionMember!) + ? _selectExpression.GetProjection(projectionBindingExpression) : entityShaperExpression.ValueBufferExpression); var innerShaper = entityProjectionExpression.BindNavigation(navigation); @@ -1529,15 +1445,9 @@ private static void HandleGroupByForAggregate(SelectExpression selectExpression, { if (eraseProjection) { - selectExpression.ReplaceProjectionMapping(new Dictionary()); - selectExpression.AddToProjection(selectExpression.GroupBy[0]); - selectExpression.PushdownIntoSubquery(); - selectExpression.ClearProjection(); - } - else - { - selectExpression.PushdownIntoSubquery(); + selectExpression.ReplaceProjection(new Dictionary()); } + selectExpression.PushdownIntoSubquery(); } } @@ -1585,19 +1495,57 @@ private Expression MatchShaperNullabilityForSetOperation(Expression shaper1, Exp } } - private ShapedQueryExpression? AggregateResultShaper( + private ShapedQueryExpression? TranslateAggregateWithSelector( ShapedQueryExpression source, - Expression? projection, + LambdaExpression? selector, + Func aggregateTranslator, bool throwWhenEmpty, Type resultType) { + var selectExpression = (SelectExpression)source.QueryExpression; + selectExpression.PrepareForAggregate(); + HandleGroupByForAggregate(selectExpression); + + SqlExpression translatedSelector; + if (selector == null + || selector.Body == selector.Parameters[0]) + { + var shaperExpression = source.ShaperExpression; + if (shaperExpression is UnaryExpression unaryExpression + && unaryExpression.NodeType == ExpressionType.Convert) + { + shaperExpression = unaryExpression.Operand; + } + + if (shaperExpression is ProjectionBindingExpression projectionBindingExpression) + { + translatedSelector = (SqlExpression)selectExpression.GetProjection(projectionBindingExpression); + } + else + { + return null; + } + } + else + { + var newSelector = RemapLambdaBody(source, selector); + if (TranslateExpression(newSelector) is SqlExpression sqlExpression) + { + translatedSelector = sqlExpression; + } + else + { + return null; + } + } + + var projection = aggregateTranslator(translatedSelector); if (projection == null) { return null; } - var selectExpression = (SelectExpression)source.QueryExpression; - selectExpression.ReplaceProjectionMapping( + selectExpression.ReplaceProjection( new Dictionary { { new ProjectionMember(), projection } }); selectExpression.ClearOrdering(); @@ -1632,7 +1580,7 @@ private Expression MatchShaperNullabilityForSetOperation(Expression shaper1, Exp returnValueForNull, resultType != resultVariable.Type ? Expression.Convert(resultVariable, resultType) - : (Expression)resultVariable)); + : resultVariable)); } else { diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs index ccde34ec354..53f409e34ac 100644 --- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs @@ -121,6 +121,7 @@ private static readonly MethodInfo _collectionAccessorAddMethodInfo // Since identifiers for collection are not part of larger lambda they don't cannot use caching to materialize only once. private bool _inline; + private int _collectionId; // States to convert code to data reader read private readonly IDictionary> _materializationContextBindings @@ -216,9 +217,11 @@ private ShaperProcessingExpressionVisitor( public LambdaExpression ProcessShaper( Expression shaperExpression, out RelationalCommandCache? relationalCommandCache, - out LambdaExpression? relatedDataLoaders) + out LambdaExpression? relatedDataLoaders, + ref int collectionId) { relatedDataLoaders = null; + _collectionId = collectionId; if (_indexMapParameter != null) { @@ -348,6 +351,8 @@ public LambdaExpression ProcessShaper( _parentVisitor._useRelationalNulls) : null; + collectionId = _collectionId; + return Expression.Lambda( result, QueryCompilationContext.QueryContextParameter, @@ -397,8 +402,7 @@ protected override Expression VisitExtension(Expression extensionExpression) { case RelationalEntityShaperExpression entityShaperExpression: { - var key = GenerateKey((ProjectionBindingExpression)entityShaperExpression.ValueBufferExpression); - if (!_variableShaperMapping.TryGetValue(key, out var accessor)) + if (!_variableShaperMapping.TryGetValue(entityShaperExpression.ValueBufferExpression, out var accessor)) { var entityParameter = Expression.Parameter(entityShaperExpression.Type); _variables.Add(entityParameter); @@ -421,7 +425,7 @@ protected override Expression VisitExtension(Expression extensionExpression) accessor = entityParameter; } - _variableShaperMapping[key] = accessor; + _variableShaperMapping[entityShaperExpression.ValueBufferExpression] = accessor; } return accessor; @@ -444,8 +448,7 @@ protected override Expression VisitExtension(Expression extensionExpression) case ProjectionBindingExpression projectionBindingExpression when !_inline: { - var key = GenerateKey(projectionBindingExpression); - if (_variableShaperMapping.TryGetValue(key, out var accessor)) + if (_variableShaperMapping.TryGetValue(projectionBindingExpression, out var accessor)) { return accessor; } @@ -487,7 +490,7 @@ protected override Expression VisitExtension(Expression extensionExpression) accessor = valueParameter; } - _variableShaperMapping[key] = accessor; + _variableShaperMapping[projectionBindingExpression] = accessor; return accessor; } @@ -498,11 +501,12 @@ protected override Expression VisitExtension(Expression extensionExpression) if (includeExpression.NavigationExpression is RelationalCollectionShaperExpression relationalCollectionShaperExpression) { + var collectionIdConstant = Expression.Constant(_collectionId++); var innerShaper = new ShaperProcessingExpressionVisitor( _parentVisitor, _resultCoordinatorParameter, _selectExpression, _dataReaderParameter, _resultContextParameter, _readerColumns) - .ProcessShaper(relationalCollectionShaperExpression.InnerShaper, out _, out _); + .ProcessShaper(relationalCollectionShaperExpression.InnerShaper, out _, out _, ref _collectionId); var entityType = entity.Type; var navigation = includeExpression.Navigation; @@ -532,8 +536,6 @@ protected override Expression VisitExtension(Expression extensionExpression) _inline = false; - var collectionIdConstant = Expression.Constant(relationalCollectionShaperExpression.CollectionId); - _includeExpressions.Add( Expression.Call( _initializeIncludeCollectionMethodInfo.MakeGenericMethod(entityType, includingEntityType), @@ -583,13 +585,15 @@ protected override Expression VisitExtension(Expression extensionExpression) else if (includeExpression.NavigationExpression is RelationalSplitCollectionShaperExpression relationalSplitCollectionShaperExpression) { + var collectionIdConstant = Expression.Constant(_collectionId++); var innerProcessor = new ShaperProcessingExpressionVisitor( _parentVisitor, _resultCoordinatorParameter, _executionStrategyParameter!, relationalSplitCollectionShaperExpression.SelectExpression, _tags!); var innerShaper = innerProcessor.ProcessShaper( relationalSplitCollectionShaperExpression.InnerShaper, out var relationalCommandCache, - out var relatedDataLoaders); + out var relatedDataLoaders, + ref _collectionId); var entityType = entity.Type; var navigation = includeExpression.Navigation; @@ -618,8 +622,6 @@ protected override Expression VisitExtension(Expression extensionExpression) innerProcessor._inline = false; - var collectionIdConstant = Expression.Constant(relationalSplitCollectionShaperExpression.CollectionId); - _includeExpressions.Add( Expression.Call( _initializeSplitIncludeCollectionMethodInfo.MakeGenericMethod(entityType, includingEntityType), @@ -699,14 +701,14 @@ protected override Expression VisitExtension(Expression extensionExpression) case RelationalCollectionShaperExpression relationalCollectionShaperExpression: { - var key = GenerateKey(relationalCollectionShaperExpression); - if (!_variableShaperMapping.TryGetValue(key, out var accessor)) + if (!_variableShaperMapping.TryGetValue(relationalCollectionShaperExpression, out var accessor)) { + var collectionIdConstant = Expression.Constant(_collectionId++); var innerShaper = new ShaperProcessingExpressionVisitor( _parentVisitor, _resultCoordinatorParameter, _selectExpression, _dataReaderParameter, _resultContextParameter, _readerColumns) - .ProcessShaper(relationalCollectionShaperExpression.InnerShaper, out _, out _); + .ProcessShaper(relationalCollectionShaperExpression.InnerShaper, out _, out _, ref _collectionId); var navigation = relationalCollectionShaperExpression.Navigation; var collectionAccessor = navigation?.GetCollectionAccessor(); @@ -733,8 +735,6 @@ protected override Expression VisitExtension(Expression extensionExpression) _inline = false; - var collectionIdConstant = Expression.Constant(relationalCollectionShaperExpression.CollectionId); - var collectionParameter = Expression.Parameter(relationalCollectionShaperExpression.Type); _variables.Add(collectionParameter); _expressions.Add( @@ -778,7 +778,7 @@ protected override Expression VisitExtension(Expression extensionExpression) typeof(IReadOnlyList)), Expression.Constant(innerShaper.Compile()))); - _variableShaperMapping[key] = accessor; + _variableShaperMapping[relationalCollectionShaperExpression] = accessor; } return accessor; @@ -786,16 +786,17 @@ protected override Expression VisitExtension(Expression extensionExpression) case RelationalSplitCollectionShaperExpression relationalSplitCollectionShaperExpression: { - var key = GenerateKey(relationalSplitCollectionShaperExpression); - if (!_variableShaperMapping.TryGetValue(key, out var accessor)) + if (!_variableShaperMapping.TryGetValue(relationalSplitCollectionShaperExpression, out var accessor)) { + var collectionIdConstant = Expression.Constant(_collectionId++); var innerProcessor = new ShaperProcessingExpressionVisitor( _parentVisitor, _resultCoordinatorParameter, _executionStrategyParameter!, relationalSplitCollectionShaperExpression.SelectExpression, _tags!); var innerShaper = innerProcessor.ProcessShaper( relationalSplitCollectionShaperExpression.InnerShaper, out var relationalCommandCache, - out var relatedDataLoaders); + out var relatedDataLoaders, + ref _collectionId); var navigation = relationalSplitCollectionShaperExpression.Navigation; var collectionAccessor = navigation?.GetCollectionAccessor(); @@ -821,8 +822,6 @@ protected override Expression VisitExtension(Expression extensionExpression) innerProcessor._inline = false; - var collectionIdConstant = Expression.Constant(relationalSplitCollectionShaperExpression.CollectionId); - var collectionParameter = Expression.Parameter(collectionType); _variables.Add(collectionParameter); _expressions.Add( @@ -865,7 +864,7 @@ protected override Expression VisitExtension(Expression extensionExpression) ? typeof(Func) : typeof(Action)))); - _variableShaperMapping[key] = accessor; + _variableShaperMapping[relationalSplitCollectionShaperExpression] = accessor; } return accessor; @@ -955,21 +954,11 @@ private static Expression AddToCollectionNavigation( relatedEntity, Expression.Constant(true)); - private Expression GenerateKey(Expression expression) - => expression is ProjectionBindingExpression projectionBindingExpression - && projectionBindingExpression.ProjectionMember != null - ? _selectExpression.GetMappedProjection(projectionBindingExpression.ProjectionMember) - : expression; - private object GetProjectionIndex(ProjectionBindingExpression projectionBindingExpression) - => projectionBindingExpression.ProjectionMember != null - ? _selectExpression.GetMappedProjection(projectionBindingExpression.ProjectionMember).GetConstantValue() - : (projectionBindingExpression.Index != null - ? (object)projectionBindingExpression.Index - : projectionBindingExpression.IndexMap)!; + => _selectExpression.GetProjection(projectionBindingExpression).GetConstantValue(); private static bool IsNullableProjection(ProjectionExpression projection) - => !(projection.Expression is ColumnExpression column) || column.IsNullable; + => projection.Expression is not ColumnExpression column || column.IsNullable; private Expression CreateGetValueExpression( ParameterExpression dbDataReader, diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.cs index a7eb2382e76..b366e43db5d 100644 --- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.cs @@ -6,6 +6,7 @@ using System.Linq; using System.Linq.Expressions; using System.Threading.Tasks; +using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; @@ -60,10 +61,16 @@ protected override Expression VisitShapedQuery(ShapedQueryExpression shapedQuery VerifyNoClientConstant(shapedQueryExpression.ShaperExpression); var nonComposedFromSql = selectExpression.IsNonComposedFromSql(); - var splitQuery = ((RelationalQueryCompilationContext)QueryCompilationContext).QuerySplittingBehavior - == QuerySplittingBehavior.SplitQuery; + var querySplittingBehavior = ((RelationalQueryCompilationContext)QueryCompilationContext).QuerySplittingBehavior; + var splitQuery = querySplittingBehavior == QuerySplittingBehavior.SplitQuery; + var collectionCount = 0; var shaper = new ShaperProcessingExpressionVisitor(this, selectExpression, _tags, splitQuery, nonComposedFromSql).ProcessShaper( - shapedQueryExpression.ShaperExpression, out var relationalCommandCache, out var relatedDataLoaders); + shapedQueryExpression.ShaperExpression, out var relationalCommandCache, out var relatedDataLoaders, ref collectionCount); + if (querySplittingBehavior == null + && collectionCount > 1) + { + QueryCompilationContext.Logger.MultipleCollectionIncludeWarning(); + } if (nonComposedFromSql) { diff --git a/src/EFCore.Relational/Query/RelationalSplitCollectionShaperExpression.cs b/src/EFCore.Relational/Query/RelationalSplitCollectionShaperExpression.cs index 02840b60969..921dc794cf2 100644 --- a/src/EFCore.Relational/Query/RelationalSplitCollectionShaperExpression.cs +++ b/src/EFCore.Relational/Query/RelationalSplitCollectionShaperExpression.cs @@ -34,6 +34,7 @@ public class RelationalSplitCollectionShaperExpression : Expression, IPrintableE /// An expression used to create individual elements of the collection. /// A navigation associated with this collection, if any. /// The clr type of individual elements in the collection. + [Obsolete("Use ctor without collectionId")] public RelationalSplitCollectionShaperExpression( int collectionId, Expression parentIdentifier, @@ -60,10 +61,45 @@ public RelationalSplitCollectionShaperExpression( ElementType = elementType; } + /// + /// Creates a new instance of the class. + /// + /// An identifier for the parent element. + /// An identifier for the child element. + /// A list of value comparers to compare identifiers. + /// A SQL query to get values for this collection from database. + /// An expression used to create individual elements of the collection. + /// A navigation associated with this collection, if any. + /// The clr type of individual elements in the collection. + public RelationalSplitCollectionShaperExpression( + Expression parentIdentifier, + Expression childIdentifier, + IReadOnlyList identifierValueComparers, + SelectExpression selectExpression, + Expression innerShaper, + INavigationBase? navigation, + Type elementType) + { + Check.NotNull(parentIdentifier, nameof(parentIdentifier)); + Check.NotNull(childIdentifier, nameof(childIdentifier)); + Check.NotEmpty(identifierValueComparers, nameof(identifierValueComparers)); + Check.NotNull(innerShaper, nameof(innerShaper)); + Check.NotNull(elementType, nameof(elementType)); + + ParentIdentifier = parentIdentifier; + ChildIdentifier = childIdentifier; + IdentifierValueComparers = identifierValueComparers; + SelectExpression = selectExpression; + InnerShaper = innerShaper; + Navigation = navigation; + ElementType = elementType; + } + /// /// A unique id for this collection shaper. /// - public virtual int CollectionId { get; } + [Obsolete("CollectionId are not stored in shaper anymore. Shaper compiler assigns it as needed.")] + public virtual int? CollectionId { get; } /// /// The identifier for the parent element. @@ -146,8 +182,7 @@ public virtual RelationalSplitCollectionShaperExpression Update( || selectExpression != SelectExpression || innerShaper != InnerShaper ? new RelationalSplitCollectionShaperExpression( - CollectionId, parentIdentifier, childIdentifier, IdentifierValueComparers, selectExpression, innerShaper, - Navigation, ElementType) + parentIdentifier, childIdentifier, IdentifierValueComparers, selectExpression, innerShaper, Navigation, ElementType) : this; } @@ -159,7 +194,6 @@ void IPrintableExpression.Print(ExpressionPrinter expressionPrinter) expressionPrinter.AppendLine("RelationalCollectionShaper:"); using (expressionPrinter.Indent()) { - expressionPrinter.AppendLine($"CollectionId: {CollectionId}"); expressionPrinter.Append("ParentIdentifier:"); expressionPrinter.Visit(ParentIdentifier); expressionPrinter.AppendLine(); diff --git a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs index 3c3596927e4..1b416ec281b 100644 --- a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs @@ -409,18 +409,87 @@ protected override Expression VisitExtension(Expression extensionExpression) case EntityShaperExpression entityShaperExpression: return new EntityReferenceExpression(entityShaperExpression); - case ProjectionBindingExpression projectionBindingExpression - when projectionBindingExpression.ProjectionMember != null: + case ProjectionBindingExpression projectionBindingExpression: return ((SelectExpression)projectionBindingExpression.QueryExpression) - .GetMappedProjection(projectionBindingExpression.ProjectionMember); - - //case ProjectionBindingExpression projectionBindingExpression - // when projectionBindingExpression.Index is int index: - // return ((SelectExpression)projectionBindingExpression.QueryExpression).Projection[index].Expression; + .GetProjection(projectionBindingExpression); case GroupByShaperExpression groupByShaperExpression: return new GroupingElementExpression(groupByShaperExpression.ElementSelector); + case ShapedQueryExpression shapedQueryExpression: + if (shapedQueryExpression.ResultCardinality == ResultCardinality.Enumerable) + { + return QueryCompilationContext.NotTranslatedExpression; + } + + var shaperExpression = shapedQueryExpression.ShaperExpression; + ProjectionBindingExpression? mappedProjectionBindingExpression = null; + + var innerExpression = shaperExpression; + Type? convertedType = null; + if (shaperExpression is UnaryExpression unaryExpression + && unaryExpression.NodeType == ExpressionType.Convert) + { + convertedType = unaryExpression.Type; + innerExpression = unaryExpression.Operand; + } + + if (innerExpression is EntityShaperExpression ese + && (convertedType == null + || convertedType.IsAssignableFrom(ese.Type))) + { + return new EntityReferenceExpression(shapedQueryExpression.UpdateShaperExpression(innerExpression)); + } + + if (innerExpression is ProjectionBindingExpression pbe + && (convertedType == null + || convertedType.MakeNullable() == innerExpression.Type)) + { + mappedProjectionBindingExpression = pbe; + } + + if (mappedProjectionBindingExpression == null + && shaperExpression is BlockExpression blockExpression + && blockExpression.Expressions.Count == 2 + && blockExpression.Expressions[0] is BinaryExpression binaryExpression + && binaryExpression.NodeType == ExpressionType.Assign + && binaryExpression.Right is ProjectionBindingExpression pbe2) + { + mappedProjectionBindingExpression = pbe2; + } + + if (mappedProjectionBindingExpression == null) + { + return QueryCompilationContext.NotTranslatedExpression; + } + + var subquery = (SelectExpression)shapedQueryExpression.QueryExpression; + var projection = subquery.GetProjection(mappedProjectionBindingExpression); + if (projection is not SqlExpression sqlExpression) + { + return QueryCompilationContext.NotTranslatedExpression; + } + + if (subquery.Tables.Count == 0) + { + return sqlExpression; + } + + subquery.ReplaceProjection(new List()); + subquery.AddToProjection(sqlExpression); + + SqlExpression scalarSubqueryExpression = new ScalarSubqueryExpression(subquery); + + if (shapedQueryExpression.ResultCardinality == ResultCardinality.SingleOrDefault + && !shaperExpression.Type.IsNullableType()) + { + scalarSubqueryExpression = _sqlExpressionFactory.Coalesce( + scalarSubqueryExpression, + (SqlExpression)Visit(shaperExpression.Type.GetDefaultValueConstant())); + } + + return scalarSubqueryExpression; + default: return QueryCompilationContext.NotTranslatedExpression; } @@ -657,80 +726,7 @@ static Expression RemapLambda(GroupingElementExpression groupingElement, LambdaE var subqueryTranslation = _queryableMethodTranslatingExpressionVisitor.TranslateSubquery(methodCallExpression); if (subqueryTranslation != null) { - static bool IsAggregateResultWithCustomShaper(MethodInfo method) - { - if (method.IsGenericMethod) - { - method = method.GetGenericMethodDefinition(); - } - - return QueryableMethods.IsAverageWithoutSelector(method) - || QueryableMethods.IsAverageWithSelector(method) - || method == QueryableMethods.MaxWithoutSelector - || method == QueryableMethods.MaxWithSelector - || method == QueryableMethods.MinWithoutSelector - || method == QueryableMethods.MinWithSelector - || QueryableMethods.IsSumWithoutSelector(method) - || QueryableMethods.IsSumWithSelector(method); - } - - if (subqueryTranslation.ResultCardinality == ResultCardinality.Enumerable) - { - return QueryCompilationContext.NotTranslatedExpression; - } - - var shaperExpression = subqueryTranslation.ShaperExpression; - var innerExpression = shaperExpression; - Type? convertedType = null; - if (shaperExpression is UnaryExpression unaryExpression - && unaryExpression.NodeType == ExpressionType.Convert) - { - convertedType = unaryExpression.Type; - innerExpression = unaryExpression.Operand; - } - - if (innerExpression is EntityShaperExpression entityShaperExpression - && (convertedType == null - || convertedType.IsAssignableFrom(entityShaperExpression.Type))) - { - return new EntityReferenceExpression(subqueryTranslation.UpdateShaperExpression(innerExpression)); - } - - if (!((innerExpression is ProjectionBindingExpression - && (convertedType == null - || convertedType.MakeNullable() == innerExpression.Type)) - || IsAggregateResultWithCustomShaper(methodCallExpression.Method))) - { - return QueryCompilationContext.NotTranslatedExpression; - } - - var subquery = (SelectExpression)subqueryTranslation.QueryExpression; - subquery.ApplyProjection(); - -#pragma warning disable IDE0046 // Convert to conditional expression - if (subquery.Tables.Count == 0 -#pragma warning restore IDE0046 // Convert to conditional expression - && methodCallExpression.Method.IsGenericMethod - && methodCallExpression.Method.GetGenericMethodDefinition() is MethodInfo genericMethod - && (genericMethod == QueryableMethods.AnyWithoutPredicate - || genericMethod == QueryableMethods.AnyWithPredicate - || genericMethod == QueryableMethods.All - || genericMethod == QueryableMethods.Contains)) - { - return subquery.Projection[0].Expression; - } - - SqlExpression scalarSubqueryExpression = new ScalarSubqueryExpression(subquery); - - if (subqueryTranslation.ResultCardinality == ResultCardinality.SingleOrDefault - && !shaperExpression.Type.IsNullableType()) - { - scalarSubqueryExpression = _sqlExpressionFactory.Coalesce( - scalarSubqueryExpression, - (SqlExpression)Visit(shaperExpression.Type.GetDefaultValueConstant())); - } - - return scalarSubqueryExpression; + return Visit(subqueryTranslation); } SqlExpression? sqlObject = null; @@ -934,7 +930,7 @@ protected override Expression VisitTypeBinary(TypeBinaryExpression typeBinaryExp var predicate = GeneratePredicateTPT(entityProjection); subSelectExpression.ApplyPredicate(predicate); - subSelectExpression.ReplaceProjectionMapping(new Dictionary()); + subSelectExpression.ReplaceProjection(new Dictionary()); if (subSelectExpression.Limit == null && subSelectExpression.Offset == null) { @@ -1115,20 +1111,9 @@ protected override Expression VisitUnary(UnaryExpression unaryExpression) SqlExpression innerProjection; var projectionBindingExpression = (ProjectionBindingExpression)entityShaper.ValueBufferExpression; - if (projectionBindingExpression.ProjectionMember != null) - { - var entityProjectionExpression = (EntityProjectionExpression)subSelectExpression.GetMappedProjection( - projectionBindingExpression.ProjectionMember); - innerProjection = entityProjectionExpression.BindProperty(property); - } - else - { - // This has to be index map since entities cannot map to just integer index - var index = projectionBindingExpression.IndexMap![property]; - innerProjection = subSelectExpression.Projection[index].Expression; - subSelectExpression.ClearProjection(); - } - + var entityProjectionExpression = (EntityProjectionExpression)subSelectExpression.GetProjection(projectionBindingExpression); + innerProjection = entityProjectionExpression.BindProperty(property); + subSelectExpression.ReplaceProjection(new List()); subSelectExpression.AddToProjection(innerProjection); return new ScalarSubqueryExpression(subSelectExpression); diff --git a/src/EFCore.Relational/Query/SqlExpressionFactory.cs b/src/EFCore.Relational/Query/SqlExpressionFactory.cs index 1fa9a3da2b6..00cc08794cf 100644 --- a/src/EFCore.Relational/Query/SqlExpressionFactory.cs +++ b/src/EFCore.Relational/Query/SqlExpressionFactory.cs @@ -966,7 +966,8 @@ private void AddOptionalDependentConditions( } private EntityProjectionExpression GetMappedEntityProjectionExpression(SelectExpression selectExpression) - => (EntityProjectionExpression)selectExpression.GetMappedProjection(new ProjectionMember()); + => (EntityProjectionExpression)selectExpression.GetProjection( + new ProjectionBindingExpression(selectExpression, new ProjectionMember(), typeof(ValueBuffer))); private SqlExpression IsNotNull(IProperty property, EntityProjectionExpression entityProjection) => IsNotNull(entityProjection.BindProperty(property)); diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.Helper.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.Helper.cs index 8a963f49dad..4703ad45b2b 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.Helper.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.Helper.cs @@ -66,97 +66,94 @@ public bool ContainsOuterReference(SelectExpression selectExpression) } } - private sealed class ProjectionBindingExpressionRemappingExpressionVisitor : ExpressionVisitor + private sealed class ProjectionMemberRemappingExpressionVisitor : ExpressionVisitor { - private readonly Expression _queryExpression; + private readonly SelectExpression _queryExpression; + private readonly Dictionary _projectionMemberMappings; - // Shifting PMs, converting PMs to index/indexMap - private IDictionary? _projectionMemberMappings; - - // Relocating index - private int[]? _indexMap; - - // Shift pending collection offset - private int? _pendingCollectionOffset; - - public ProjectionBindingExpressionRemappingExpressionVisitor(Expression queryExpression) + public ProjectionMemberRemappingExpressionVisitor( + SelectExpression queryExpression, Dictionary projectionMemberMappings) { _queryExpression = queryExpression; + _projectionMemberMappings = projectionMemberMappings; } - public Expression RemapProjectionMember( - Expression expression, - IDictionary projectionMemberMappings, - int pendingCollectionOffset = 0) + [return: NotNullIfNotNull("expression")] + public override Expression? Visit(Expression? expression) { - _projectionMemberMappings = projectionMemberMappings; - _indexMap = null; - _pendingCollectionOffset = pendingCollectionOffset; + if (expression is ProjectionBindingExpression projectionBindingExpression) + { + Check.DebugAssert(projectionBindingExpression.ProjectionMember != null, + "ProjectionBindingExpression must have projection member."); + + return new ProjectionBindingExpression( + _queryExpression, + _projectionMemberMappings[projectionBindingExpression.ProjectionMember], + projectionBindingExpression.Type); + } - return Visit(expression); + return base.Visit(expression); } + } - public Expression RemapIndex(Expression expression, int[] indexMap, int pendingCollectionOffset = 0) - { - _projectionMemberMappings = null; - _indexMap = indexMap; - _pendingCollectionOffset = pendingCollectionOffset; + private sealed class ProjectionMemberToIndexConvertingExpressionVisitor : ExpressionVisitor + { + private readonly SelectExpression _queryExpression; + private readonly Dictionary _projectionMemberMappings; - return Visit(expression); + public ProjectionMemberToIndexConvertingExpressionVisitor( + SelectExpression queryExpression, Dictionary projectionMemberMappings) + { + _queryExpression = queryExpression; + _projectionMemberMappings = projectionMemberMappings; } - protected override Expression VisitExtension(Expression extensionExpression) + [return: NotNullIfNotNull("expression")] + public override Expression? Visit(Expression? expression) { - return extensionExpression switch + if (expression is ProjectionBindingExpression projectionBindingExpression) { - ProjectionBindingExpression projectionBindingExpression => Remap(projectionBindingExpression), - CollectionShaperExpression collectionShaperExpression => Remap(collectionShaperExpression), - _ => base.VisitExtension(extensionExpression) - }; - } + Check.DebugAssert(projectionBindingExpression.ProjectionMember != null, + "ProjectionBindingExpression must have projection member."); - private CollectionShaperExpression Remap(CollectionShaperExpression collectionShaperExpression) - => new( - new ProjectionBindingExpression( + return new ProjectionBindingExpression( _queryExpression, - ((ProjectionBindingExpression)collectionShaperExpression.Projection).Index!.Value + (int)_pendingCollectionOffset!, - typeof(object)), - collectionShaperExpression.InnerShaper, - collectionShaperExpression.Navigation, - collectionShaperExpression.ElementType); + _projectionMemberMappings[projectionBindingExpression.ProjectionMember], + projectionBindingExpression.Type); + } + + return base.Visit(expression); + } + } - private ProjectionBindingExpression Remap(ProjectionBindingExpression projectionBindingExpression) + private sealed class ProjectionIndexRemappingExpressionVisitor : ExpressionVisitor + { + private readonly SelectExpression _queryExpression; + private readonly int[] _indexMap; + + public ProjectionIndexRemappingExpressionVisitor( + SelectExpression queryExpression, int[] indexMap) { - if (_indexMap != null) - { - if (projectionBindingExpression.Index is int index) - { - return CreateNewBinding(_indexMap[index], projectionBindingExpression.Type); - } + _queryExpression = queryExpression; + _indexMap = indexMap; + } - var indexMap = new Dictionary(); - foreach (var item in projectionBindingExpression.IndexMap!) - { - indexMap[item.Key] = _indexMap[item.Value]; - } + [return: NotNullIfNotNull("expression")] + public override Expression? Visit(Expression? expression) + { + if (expression is ProjectionBindingExpression projectionBindingExpression) + { + Check.DebugAssert(projectionBindingExpression.Index != null, + "ProjectionBindingExpression must have index."); - return CreateNewBinding(indexMap, projectionBindingExpression.Type); + return new ProjectionBindingExpression( + _queryExpression, + _indexMap[projectionBindingExpression.Index.Value], + projectionBindingExpression.Type); } - var currentProjectionMember = projectionBindingExpression.ProjectionMember; - var newBinding = _projectionMemberMappings![currentProjectionMember!]; - - return CreateNewBinding(newBinding, projectionBindingExpression.Type); + return base.Visit(expression); } - - private ProjectionBindingExpression CreateNewBinding(object binding, Type type) - => binding switch - { - ProjectionMember projectionMember => new ProjectionBindingExpression(_queryExpression, projectionMember, type), - int index => new ProjectionBindingExpression(_queryExpression, index, type), - IReadOnlyDictionary indexMap => new ProjectionBindingExpression(_queryExpression, indexMap), - _ => throw new InvalidOperationException(), - }; } private sealed class SqlRemappingVisitor : ExpressionVisitor @@ -194,9 +191,9 @@ when _mappings.TryGetValue(sqlExpression, out var outer): case ColumnExpression columnExpression when _subquery.ContainsTableReference(columnExpression): - var index = _subquery.AddToProjection(columnExpression); - var projectionExpression = _subquery._projection[index]; - return new ConcreteColumnExpression(projectionExpression, _tableReferenceExpression); + var outerColumn = _subquery.GenerateOuterColumn(_tableReferenceExpression, columnExpression); + _mappings[columnExpression] = outerColumn; + return outerColumn; default: return base.Visit(expression); @@ -469,5 +466,123 @@ private bool Equals(ConcreteColumnExpression concreteColumnExpression) public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), Name, _table, IsNullable); } + + private struct SingleCollectionInfo + { + public SingleCollectionInfo( + Expression parentIdentifier, + Expression outerIdentifier, + Expression selfIdentifier, + IReadOnlyList parentIdentifierValueComparers, + IReadOnlyList outerIdentifierValueComparers, + IReadOnlyList selfIdentifierValueComparers, + Expression shaperExpression) + { + ParentIdentifier = parentIdentifier; + OuterIdentifier = outerIdentifier; + SelfIdentifier = selfIdentifier; + ParentIdentifierValueComparers = parentIdentifierValueComparers; + OuterIdentifierValueComparers = outerIdentifierValueComparers; + SelfIdentifierValueComparers = selfIdentifierValueComparers; + ShaperExpression = shaperExpression; + } + + public Expression ParentIdentifier { get; } + public Expression OuterIdentifier { get; } + public Expression SelfIdentifier { get; } + public IReadOnlyList ParentIdentifierValueComparers { get; } + public IReadOnlyList OuterIdentifierValueComparers { get; } + public IReadOnlyList SelfIdentifierValueComparers { get; } + public Expression ShaperExpression { get; } + } + + private struct SplitCollectionInfo + { + public SplitCollectionInfo( + Expression parentIdentifier, + Expression childIdentifier, + IReadOnlyList identifierValueComparers, + SelectExpression selectExpression, + Expression shaperExpression) + { + ParentIdentifier = parentIdentifier; + ChildIdentifier = childIdentifier; + IdentifierValueComparers = identifierValueComparers; + SelectExpression = selectExpression; + ShaperExpression = shaperExpression; + } + + public Expression ParentIdentifier { get; } + public Expression ChildIdentifier { get; } + public IReadOnlyList IdentifierValueComparers { get; } + public SelectExpression SelectExpression { get; } + public Expression ShaperExpression { get; } + } + + private sealed class ClientProjectionRemappingExpressionVisitor : ExpressionVisitor + { + private readonly object[] _clientProjectionIndexMap; + + public ClientProjectionRemappingExpressionVisitor(object[] clientProjectionIndexMap) + { + _clientProjectionIndexMap = clientProjectionIndexMap; + } + + [return: NotNullIfNotNull("expression")] + public override Expression? Visit(Expression? expression) + { + if (expression is ProjectionBindingExpression projectionBindingExpression) + { + var value = _clientProjectionIndexMap[projectionBindingExpression.Index!.Value]; + if (value is int intValue) + { + return new ProjectionBindingExpression( + projectionBindingExpression.QueryExpression, intValue, projectionBindingExpression.Type); + } + + if (value is Expression innerShaper) + { + return innerShaper; + } + + throw new InvalidCastException(); + } + + if (expression is CollectionResultExpression collectionResultExpression) + { + var innerProjectionBindingExpression = collectionResultExpression.ProjectionBindingExpression; + var value = _clientProjectionIndexMap[innerProjectionBindingExpression.Index!.Value]; + if (value is SingleCollectionInfo singleCollectionInfo) + { + return new RelationalCollectionShaperExpression( + singleCollectionInfo.ParentIdentifier, + singleCollectionInfo.OuterIdentifier, + singleCollectionInfo.SelfIdentifier, + singleCollectionInfo.ParentIdentifierValueComparers, + singleCollectionInfo.OuterIdentifierValueComparers, + singleCollectionInfo.SelfIdentifierValueComparers, + singleCollectionInfo.ShaperExpression, + collectionResultExpression.Navigation, + collectionResultExpression.ElementType); + } + + if (value is SplitCollectionInfo splitCollectionInfo) + { + return new RelationalSplitCollectionShaperExpression( + splitCollectionInfo.ParentIdentifier, + splitCollectionInfo.ChildIdentifier, + splitCollectionInfo.IdentifierValueComparers, + splitCollectionInfo.SelectExpression, + splitCollectionInfo.ShaperExpression, + collectionResultExpression.Navigation, + collectionResultExpression.ElementType); + } + + throw new InvalidOperationException(); + } + + return base.Visit(expression); + } + } } } diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs index 1ad6ce0ffe4..ceb7e85dd1f 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs @@ -49,14 +49,15 @@ public sealed partial class SelectExpression : TableExpressionBase private readonly List _tableReferences = new(); private readonly List _groupBy = new(); private readonly List _orderings = new(); - private readonly HashSet _usedAliases = new(); + private HashSet _usedAliases = new(); private readonly List<(ColumnExpression Column, ValueComparer Comparer)> _identifier = new(); private readonly List<(ColumnExpression Column, ValueComparer Comparer)> _childIdentifiers = new(); - private readonly List _pendingCollections = new(); private readonly List _tptLeftJoinTables = new(); private Dictionary _projectionMapping = new(); + private List _clientProjections = new(); + private readonly List _aliasForClientProjections = new(); private SelectExpression( string? alias, @@ -315,7 +316,8 @@ public void ApplyTags(ISet tags) /// public void ApplyDistinct() { - if (_pendingCollections.Count > 0) + if (_clientProjections.Count > 0 + && _clientProjections.Any(e => e is ShapedQueryExpression sqe && sqe.ResultCardinality == ResultCardinality.Enumerable)) { throw new InvalidOperationException(RelationalStrings.DistinctOnCollectionNotSupported); } @@ -328,45 +330,45 @@ public void ApplyDistinct() IsDistinct = true; - if (_projection.Count > 0) - { - // _childIdentifiers are empty at this point since we are still in translation phase - if (!_identifier.All(e => _projection.Any(p => e.Column.Equals(p.Expression)))) - { - _identifier.Clear(); - // If identifier is not in the list then we add whole current projection as identifier if all column expressions - if (_projection.All(p => p.Expression is ColumnExpression)) - { - _identifier.AddRange(_projection.Select(p => ((ColumnExpression)p.Expression, p.Expression.TypeMapping!.KeyComparer))); - } - } - } - else + if (_identifier.Count > 0) { - if (_identifier.Count > 0) + var entityProjectionIdentifiers = new List(); + var entityProjectionValueComparers = new List(); + var otherExpressions = new List(); + var nonProcessableExpressionFound = false; + + var projections = _clientProjections.Count > 0 ? _clientProjections : _projectionMapping.Values.ToList(); + foreach (var projection in projections) { - var entityProjectionIdentifiers = new List(); - var entityProjectionValueComparers = new List(); - var otherExpressions = new List(); - foreach (var projectionMapping in _projectionMapping) + if (projection is EntityProjectionExpression entityProjection) { - if (projectionMapping.Value is EntityProjectionExpression entityProjection) - { - var primaryKey = entityProjection.EntityType.FindPrimaryKey(); - // If there are any existing identifier then all entity projection must have a key - // else keyless entity would have wiped identifier when generating join. - Check.DebugAssert(primaryKey != null, "primary key is null."); - foreach (var property in primaryKey.Properties) - { - entityProjectionIdentifiers.Add(entityProjection.BindProperty(property)); - entityProjectionValueComparers.Add(property.GetKeyValueComparer()); - } - } - else if (projectionMapping.Value is SqlExpression sqlExpression) + var primaryKey = entityProjection.EntityType.FindPrimaryKey(); + // If there are any existing identifier then all entity projection must have a key + // else keyless entity would have wiped identifier when generating join. + Check.DebugAssert(primaryKey != null, "primary key is null."); + foreach (var property in primaryKey.Properties) { - otherExpressions.Add(sqlExpression); + entityProjectionIdentifiers.Add(entityProjection.BindProperty(property)); + entityProjectionValueComparers.Add(property.GetKeyValueComparer()); } } + else if (projection is SqlExpression sqlExpression) + { + otherExpressions.Add(sqlExpression); + } + else + { + nonProcessableExpressionFound = true; + break; + } + } + + if (nonProcessableExpressionFound) + { + _identifier.Clear(); + } + else + { var allOtherExpressions = entityProjectionIdentifiers.Concat(otherExpressions).ToList(); if (!_identifier.All(e => allOtherExpressions.Contains(e.Column))) { @@ -391,525 +393,622 @@ public void ApplyDistinct() /// /// Adds expressions from projection mapping to projection if not done already. /// - public void ApplyProjection() + public Expression ApplyProjection(Expression shaperExpression, QuerySplittingBehavior querySplittingBehavior) { if (Projection.Any()) { - return; + throw new InvalidOperationException("Applying projection on already finalized select expression"); } - var result = new Dictionary(); - var mapping = ApplyProjectionMapping(_projectionMapping); - foreach (var keyValuePair in mapping) + if (_clientProjections.Count > 0) { - result[keyValuePair.Key] = Constant(mapping[keyValuePair.Key]); - } + if (_clientProjections.Any(e => e is ShapedQueryExpression) + && (Limit != null + || Offset != null + || IsDistinct + || GroupBy.Count > 0)) + { + PushdownIntoSubqueryInternal(); + } + var projectionCount = _clientProjections.Count; + var newClientProjections = new List(); + var clientProjectionIndexMap = new object[projectionCount]; + var remappingRequired = false; + for (var i = 0; i < projectionCount; i++) + { + var value = _clientProjections[i]; + switch (value) + { + case EntityProjectionExpression entityProjection: + { + var result = AddEntityProjection(entityProjection); + newClientProjections.Add(result); + clientProjectionIndexMap[i] = newClientProjections.Count - 1; - _projectionMapping = result; - } + break; + } - /// - /// Clears all existing projections. - /// - public void ClearProjection() - { - _projection.Clear(); - } + case SqlExpression sqlExpression: + { + var result = Constant(AddToProjection(sqlExpression, _aliasForClientProjections[i])); + newClientProjections.Add(result); + clientProjectionIndexMap[i] = newClientProjections.Count - 1; - /// - /// Replaces current projection mapping with a new one to change what is being projected out from this . - /// - /// A new projection mapping. - public void ReplaceProjectionMapping(IDictionary projectionMapping) - { - Check.NotNull(projectionMapping, nameof(projectionMapping)); + break; + } - _projectionMapping.Clear(); - foreach (var kvp in projectionMapping) - { - _projectionMapping[kvp.Key] = kvp.Value; - } - } + case ShapedQueryExpression shapedQueryExpression + when shapedQueryExpression.ResultCardinality == ResultCardinality.Single + || shapedQueryExpression.ResultCardinality == ResultCardinality.SingleOrDefault: + { + var innerSelectExpression = (SelectExpression)shapedQueryExpression.QueryExpression; + var innerShaperExpression = shapedQueryExpression.ShaperExpression; + if (innerSelectExpression._clientProjections.Count == 0) + { + var mapping = innerSelectExpression.ConvertProjectionMappingToClientProjections( + innerSelectExpression._projectionMapping); + innerShaperExpression = new ProjectionMemberToIndexConvertingExpressionVisitor(innerSelectExpression, mapping) + .Visit(innerShaperExpression); + } - /// - /// Gets the projection mapped to the given . - /// - /// A projection member to search in the mapping. - /// The mapped projection for given projection member. - public Expression GetMappedProjection(ProjectionMember projectionMember) - { - Check.NotNull(projectionMember, nameof(projectionMember)); + var innerExpression = RemoveConvert(innerShaperExpression); + if (!(innerExpression is EntityShaperExpression + || innerExpression is IncludeExpression)) + { + var sentinelExpression = innerSelectExpression.Limit!; + var sentinelNullableType = sentinelExpression.Type.MakeNullable(); + ProjectionBindingExpression dummyProjection; + innerSelectExpression._clientProjections.Add(sentinelExpression); + innerSelectExpression._aliasForClientProjections.Add(null); + dummyProjection = new ProjectionBindingExpression( + innerSelectExpression, innerSelectExpression._clientProjections.Count - 1, sentinelNullableType); + + var defaultResult = shapedQueryExpression.ResultCardinality == ResultCardinality.SingleOrDefault + ? (Expression)Default(innerShaperExpression.Type) + : Block( + Throw( + New( + typeof(InvalidOperationException).GetConstructors() + .Single(ci => + { + var parameters = ci.GetParameters(); + return parameters.Length == 1 && parameters[0].ParameterType == typeof(string); + }), + Constant(CoreStrings.SequenceContainsNoElements))), + Default(innerShaperExpression.Type)); + + innerShaperExpression = Condition( + Equal(dummyProjection, Default(sentinelNullableType)), + defaultResult, + innerShaperExpression); + } - return _projectionMapping[projectionMember]; - } + innerShaperExpression = innerSelectExpression.ApplyProjection(innerShaperExpression, querySplittingBehavior); + AddJoin(JoinType.OuterApply, ref innerSelectExpression); - /// - /// Adds given to the projection. - /// - /// An entity projection to add. - /// A dictionary of to int indicating properties and their corresponding indexes in the projection list. - public IReadOnlyDictionary AddToProjection(EntityProjectionExpression entityProjection) - { - Check.NotNull(entityProjection, nameof(entityProjection)); + innerShaperExpression = CopyProjectionToOuter(innerSelectExpression, innerShaperExpression); + clientProjectionIndexMap[i] = innerShaperExpression; + remappingRequired = true; + break; - var dictionary = new Dictionary(); - foreach (var property in GetAllPropertiesInHierarchy(entityProjection.EntityType)) - { - dictionary[property] = AddToProjection(entityProjection.BindProperty(property)); - } + static Expression RemoveConvert(Expression expression) + => expression is UnaryExpression unaryExpression + && unaryExpression.NodeType == ExpressionType.Convert + ? RemoveConvert(unaryExpression.Operand) + : expression; + } - if (entityProjection.DiscriminatorExpression != null) - { - AddToProjection(entityProjection.DiscriminatorExpression, _discriminatorColumnAlias); - } + case ShapedQueryExpression shapedQueryExpression + when shapedQueryExpression.ResultCardinality == ResultCardinality.Enumerable: + { + var innerSelectExpression = (SelectExpression)shapedQueryExpression.QueryExpression; + if (_identifier.Count == 0 + || innerSelectExpression._identifier.Count == 0) + { + throw new InvalidOperationException(RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin); + } - return dictionary; - } + var innerShaperExpression = shapedQueryExpression.ShaperExpression; + if (innerSelectExpression._clientProjections.Count == 0) + { + var mapping = innerSelectExpression.ConvertProjectionMappingToClientProjections( + innerSelectExpression._projectionMapping); + innerShaperExpression = new ProjectionMemberToIndexConvertingExpressionVisitor(innerSelectExpression, mapping) + .Visit(innerShaperExpression); + } - /// - /// Adds given to the projection. - /// - /// An expression to add. - /// An int value indicating the index at which the expression was added in the projection list. - public int AddToProjection(SqlExpression sqlExpression) - { - Check.NotNull(sqlExpression, nameof(sqlExpression)); + if (querySplittingBehavior == QuerySplittingBehavior.SplitQuery) + { + var containsReferenceToOuter = new SelectExpressionCorrelationFindingExpressionVisitor(this) + .ContainsOuterReference(innerSelectExpression); + if (containsReferenceToOuter) + { + throw new InvalidOperationException( + RelationalStrings.UnableToSplitCollectionProjectionInSplitQuery( + $"{nameof(QuerySplittingBehavior)}.{QuerySplittingBehavior.SplitQuery}", + nameof(RelationalQueryableExtensions.AsSplitQuery), + nameof(RelationalQueryableExtensions.AsSingleQuery))); + } - return AddToProjection(sqlExpression, null); - } + var identifierFromParent = _identifier; + if (innerSelectExpression.Tables.LastOrDefault(e => e is InnerJoinExpression) is InnerJoinExpression + collectionInnerJoinExpression + && collectionInnerJoinExpression.Table is TableExpressionBase collectionTableExpressionBase) + { + // This computes true parent identifier count for correlation. + // The last inner joined table in innerSelectExpression brings collection data. + // Further tables load additional data on the collection (hence uses outer pattern) + // So identifier not coming from there (which would be at the start only) are for correlation with parent. + // Parent can have additional identifier if a owned reference was expanded. + var actualParentIdentifierCount = innerSelectExpression._identifier + .TakeWhile(e => !ReferenceEquals(e.Column.Table, collectionTableExpressionBase)) + .Count(); + identifierFromParent = _identifier.Take(actualParentIdentifierCount).ToList(); + } - private int AddToProjection(SqlExpression sqlExpression, string? alias) - { - var existingIndex = _projection.FindIndex(pe => pe.Expression.Equals(sqlExpression)); - if (existingIndex != -1) - { - return existingIndex; - } + var parentIdentifier = GetIdentifierAccessor(this, newClientProjections, identifierFromParent).Item1; + innerShaperExpression = innerSelectExpression.ApplyProjection(innerShaperExpression, querySplittingBehavior); - var baseAlias = !string.IsNullOrEmpty(alias) - ? alias - : (sqlExpression as ColumnExpression)?.Name; - if (Alias != null) - { - baseAlias ??= "c"; - var counter = 0; + for (var j = 0; j < identifierFromParent.Count; j++) + { + AppendOrdering(new OrderingExpression(identifierFromParent[j].Column, ascending: true)); + } - var currentAlias = baseAlias; - while (_projection.Any(pe => string.Equals(pe.Alias, currentAlias, StringComparison.OrdinalIgnoreCase))) - { - currentAlias = $"{baseAlias}{counter++}"; - } + // Copy over ordering from previous collections + var innerOrderingExpressions = new List(); + for (var j = 0; j < innerSelectExpression.Tables.Count; j++) + { + var table = innerSelectExpression.Tables[j]; + if (table is InnerJoinExpression collectionJoinExpression + && collectionJoinExpression.Table is SelectExpression collectionSelectExpression + && collectionSelectExpression.Predicate != null + && collectionSelectExpression.Tables.Count == 1 + && collectionSelectExpression.Tables[0] is SelectExpression rowNumberSubquery + && rowNumberSubquery.Projection.Select(pe => pe.Expression) + .OfType().SingleOrDefault() is RowNumberExpression rowNumberExpression) + { + var collectionSelectExpressionTableReference = innerSelectExpression._tableReferences[j]; + var rowNumberSubqueryTableReference = collectionSelectExpression._tableReferences.Single(); + foreach (var partition in rowNumberExpression.Partitions) + { + innerOrderingExpressions.Add( + new OrderingExpression( + collectionSelectExpression.GenerateOuterColumn( + collectionSelectExpressionTableReference, + rowNumberSubquery.GenerateOuterColumn(rowNumberSubqueryTableReference, partition)), + ascending: true)); + } + + foreach (var ordering in rowNumberExpression.Orderings) + { + innerOrderingExpressions.Add( + new OrderingExpression( + collectionSelectExpression.GenerateOuterColumn( + collectionSelectExpressionTableReference, + rowNumberSubquery.GenerateOuterColumn(rowNumberSubqueryTableReference, ordering.Expression)), + ordering.IsAscending)); + } + } - baseAlias = currentAlias; - } + if (table is CrossApplyExpression collectionApplyExpression + && collectionApplyExpression.Table is SelectExpression collectionSelectExpression2 + && collectionSelectExpression2.Orderings.Count > 0) + { + var collectionSelectExpressionTableReference = innerSelectExpression._tableReferences[j]; + foreach (var ordering in collectionSelectExpression2.Orderings) + { + if (innerSelectExpression._identifier.Any(e => e.Column.Equals(ordering.Expression))) + { + continue; + } + + innerOrderingExpressions.Add( + new OrderingExpression( + collectionSelectExpression2.GenerateOuterColumn(collectionSelectExpressionTableReference, ordering.Expression), + ordering.IsAscending)); + } + } + } - sqlExpression = AssignUniqueAliases(sqlExpression); - _projection.Add(new ProjectionExpression(sqlExpression, baseAlias ?? "")); + var (childIdentifier, childIdentifierValueComparers) = GetIdentifierAccessor( + innerSelectExpression, + innerSelectExpression._clientProjections, + innerSelectExpression._identifier.Take(identifierFromParent.Count)); - return _projection.Count - 1; - } + var identifierIndex = 0; + var orderingIndex = 0; + for (var j = 0; j < Orderings.Count; j++) + { + var outerOrdering = Orderings[j]; + if (identifierIndex < identifierFromParent.Count + && outerOrdering.Expression.Equals(identifierFromParent[identifierIndex].Column)) + { + innerSelectExpression.AppendOrdering( + new OrderingExpression( + innerSelectExpression._identifier[identifierIndex].Column, ascending: true)); + identifierIndex++; + } + else + { + if (j < innerSelectExpression.Orderings.Count) + { + continue; + } - /// - /// Adds a non-scalar single result to the projection of the . - /// - /// A shaped query expression for the subquery producing single non-scalar result. - /// A shaper expression to shape the result of this projection. - public Expression AddSingleProjection(ShapedQueryExpression shapedQueryExpression) - { - Check.NotNull(shapedQueryExpression, nameof(shapedQueryExpression)); + innerSelectExpression.AppendOrdering(innerOrderingExpressions[orderingIndex]); + orderingIndex++; + } + } - var innerSelectExpression = (SelectExpression)shapedQueryExpression.QueryExpression; - var shaperExpression = shapedQueryExpression.ShaperExpression; - var innerExpression = RemoveConvert(shaperExpression); - if (!(innerExpression is EntityShaperExpression)) - { - var sentinelExpression = innerSelectExpression.Limit!; - var sentinelNullableType = sentinelExpression.Type.MakeNullable(); - ProjectionBindingExpression dummyProjection; - if (innerSelectExpression.Projection.Any()) - { - var index = innerSelectExpression.AddToProjection(sentinelExpression); - dummyProjection = new ProjectionBindingExpression(innerSelectExpression, index, sentinelNullableType); - } - else - { - innerSelectExpression._projectionMapping[new ProjectionMember()] = sentinelExpression; - dummyProjection = new ProjectionBindingExpression(innerSelectExpression, new ProjectionMember(), sentinelNullableType); - } + foreach (var orderingExpression in innerOrderingExpressions.Skip(orderingIndex)) + { + innerSelectExpression.AppendOrdering(orderingExpression); + } + + var result = new SplitCollectionInfo( + parentIdentifier, childIdentifier, childIdentifierValueComparers, + innerSelectExpression, innerShaperExpression); + clientProjectionIndexMap[i] = result; + } + else + { + var parentIdentifierList = _identifier.Except(_childIdentifiers, _identifierComparer).ToList(); + var (parentIdentifier, parentIdentifierValueComparers) = GetIdentifierAccessor( + this, newClientProjections, parentIdentifierList); + var (outerIdentifier, outerIdentifierValueComparers) = GetIdentifierAccessor( + this, newClientProjections, _identifier); + + foreach (var identifier in _identifier) + { + AppendOrdering(new OrderingExpression(identifier.Column, ascending: true)); + } - var defaultResult = shapedQueryExpression.ResultCardinality == ResultCardinality.SingleOrDefault - ? (Expression)Default(shaperExpression.Type) - : Block( - Throw( - New( - typeof(InvalidOperationException).GetConstructors() - .Single(ci => + innerShaperExpression = innerSelectExpression.ApplyProjection(innerShaperExpression, querySplittingBehavior); + AddJoin(JoinType.OuterApply, ref innerSelectExpression); + var innerOrderingExpressions = new List(); + var joinedTable = innerSelectExpression.Tables.Single(); + if (joinedTable is SelectExpression collectionSelectExpression + && collectionSelectExpression.Predicate != null + && collectionSelectExpression.Tables.Count == 1 + && collectionSelectExpression.Tables[0] is SelectExpression rowNumberSubquery + && rowNumberSubquery.Projection.Select(pe => pe.Expression) + .OfType().SingleOrDefault() is RowNumberExpression rowNumberExpression) + { + var collectionSelectExpressionTableReference = innerSelectExpression._tableReferences.Single(); + var rowNumberSubqueryTableReference = collectionSelectExpression._tableReferences.Single(); + foreach (var partition in rowNumberExpression.Partitions) { - var parameters = ci.GetParameters(); - return parameters.Length == 1 && parameters[0].ParameterType == typeof(string); - }), - Constant(CoreStrings.SequenceContainsNoElements))), - Default(shaperExpression.Type)); - - shaperExpression = Condition( - Equal(dummyProjection, Default(sentinelNullableType)), - defaultResult, - shaperExpression); - } - - var remapper = new ProjectionBindingExpressionRemappingExpressionVisitor(this); - // Pending collections from inner are lifted to outer when adding join - // So we need to update offsets in shaper - var pendingCollectionOffset = _pendingCollections.Count; - AddJoin(JoinType.OuterApply, ref innerSelectExpression); - var projectionCount = innerSelectExpression.Projection.Count; + innerOrderingExpressions.Add( + new OrderingExpression( + collectionSelectExpression.GenerateOuterColumn( + collectionSelectExpressionTableReference, + rowNumberSubquery.GenerateOuterColumn(rowNumberSubqueryTableReference, partition)), + ascending: true)); + } - if (projectionCount > 0) - { - var indexMap = new int[projectionCount]; - for (var i = 0; i < projectionCount; i++) - { - var projectionToAdd = innerSelectExpression.Projection[i].Expression; - projectionToAdd = MakeNullable(projectionToAdd, nullable: true); - indexMap[i] = AddToProjection(projectionToAdd); - } + foreach (var ordering in rowNumberExpression.Orderings) + { + innerOrderingExpressions.Add( + new OrderingExpression( + collectionSelectExpression.GenerateOuterColumn( + collectionSelectExpressionTableReference, + rowNumberSubquery.GenerateOuterColumn(rowNumberSubqueryTableReference, ordering.Expression)), + ordering.IsAscending)); + } + } + else if (joinedTable is SelectExpression collectionSelectExpression2 + && collectionSelectExpression2.Orderings.Count > 0) + { + var collectionSelectExpressionTableReference = innerSelectExpression._tableReferences.Single(); + foreach (var ordering in collectionSelectExpression2.Orderings) + { + if (innerSelectExpression._identifier.Any(e => e.Column.Equals(ordering.Expression))) + { + continue; + } + + innerOrderingExpressions.Add( + new OrderingExpression( + collectionSelectExpression2.GenerateOuterColumn(collectionSelectExpressionTableReference, ordering.Expression), + ordering.IsAscending)); + } + } + else + { + innerOrderingExpressions.AddRange(innerSelectExpression.Orderings); + } - shaperExpression = remapper.RemapIndex(shaperExpression, indexMap, pendingCollectionOffset); - } - else - { - var mapping = ApplyProjectionMapping(innerSelectExpression._projectionMapping, makeNullable: true); - shaperExpression = remapper.RemapProjectionMember(shaperExpression, mapping, pendingCollectionOffset); - } + foreach (var ordering in innerOrderingExpressions) + { + AppendOrdering(ordering.Update(MakeNullable(ordering.Expression, nullable: true))); + } - return new EntityShaperNullableMarkingExpressionVisitor().Visit(shaperExpression); + innerShaperExpression = CopyProjectionToOuter(innerSelectExpression, innerShaperExpression); + var (selfIdentifier, selfIdentifierValueComparers) = GetIdentifierAccessor( + this, + newClientProjections, + innerSelectExpression._identifier + .Except(innerSelectExpression._childIdentifiers, _identifierComparer) + .Select(e => (e.Column.MakeNullable(), e.Comparer))); - static Expression RemoveConvert(Expression expression) - => expression is UnaryExpression unaryExpression - && unaryExpression.NodeType == ExpressionType.Convert - ? RemoveConvert(unaryExpression.Operand) - : expression; - } + foreach (var identifier in innerSelectExpression._identifier) + { + var updatedColumn = identifier.Column.MakeNullable(); + _childIdentifiers.Add((updatedColumn, identifier.Comparer)); + AppendOrdering(new OrderingExpression(updatedColumn, ascending: true)); + } - /// - /// Adds a collection to the projection of the . - /// - /// A shaped query expression for the subquery producing collection result. - /// A navigation associated with this collection, if any. - /// The type of the element in the collection. - /// A which represents shaping of this collection. - public CollectionShaperExpression AddCollectionProjection( - ShapedQueryExpression shapedQueryExpression, INavigationBase? navigation, Type elementType) - { - Check.NotNull(shapedQueryExpression, nameof(shapedQueryExpression)); + var result = new SingleCollectionInfo( + parentIdentifier, outerIdentifier, selfIdentifier, + parentIdentifierValueComparers, outerIdentifierValueComparers, selfIdentifierValueComparers, + innerShaperExpression); + clientProjectionIndexMap[i] = result; + } + remappingRequired = true; - var innerSelectExpression = (SelectExpression)shapedQueryExpression.QueryExpression; - _pendingCollections.Add(innerSelectExpression); + static (Expression, IReadOnlyList) GetIdentifierAccessor( + SelectExpression selectExpression, + List clientProjectionList, + IEnumerable<(ColumnExpression Column, ValueComparer Comparer)> identifyingProjection) + { + var updatedExpressions = new List(); + var comparers = new List(); + foreach (var keyExpression in identifyingProjection) + { + var index = selectExpression.AddToProjection(keyExpression.Column, null); + var clientProjectionToAdd = Constant(index); + var existingIndex = clientProjectionList.FindIndex( + e => ExpressionEqualityComparer.Instance.Equals(e, clientProjectionToAdd)); + if (existingIndex == -1) + { + clientProjectionList.Add(Constant(index)); + existingIndex = clientProjectionList.Count - 1; + } - return new CollectionShaperExpression( - new ProjectionBindingExpression(this, _pendingCollections.Count - 1, typeof(object)), - shapedQueryExpression.ShaperExpression, - navigation, - elementType); - } + var projectionBindingExpression = new ProjectionBindingExpression( + selectExpression, existingIndex, keyExpression.Column.Type.MakeNullable()); - /// - /// Applies previously added collection projection. - /// - /// An int value specifing which collection from pending collection to apply. - /// An int value of unique collection id associated with this collection projection. - /// A shaper expression to use for shaping the elements of this collection. - /// A navigation associated with this collection, if any. - /// The type of the element in the collection. - /// A value indicating whether the collection query would be run with a different DbCommand. - /// An expression which represents shaping of this collection. - public Expression? ApplyCollectionJoin( - int collectionIndex, - int collectionId, - Expression innerShaper, - INavigationBase? navigation, - Type elementType, - bool splitQuery = false) - { - Check.NotNull(innerShaper, nameof(innerShaper)); - Check.NotNull(elementType, nameof(elementType)); + updatedExpressions.Add( + projectionBindingExpression.Type.IsValueType + ? Convert(projectionBindingExpression, typeof(object)) + : projectionBindingExpression); + comparers.Add(keyExpression.Comparer); + } - var innerSelectExpression = _pendingCollections[collectionIndex]!; - _pendingCollections[collectionIndex] = null; + return (NewArrayInit(typeof(object), updatedExpressions), comparers); + } - if (_identifier.Count == 0 - || innerSelectExpression._identifier.Count == 0) - { - throw new InvalidOperationException(RelationalStrings.InsufficientInformationToIdentifyOuterElementOfCollectionJoin); - } + break; + } - if (splitQuery) - { - var containsReferenceToOuter = new SelectExpressionCorrelationFindingExpressionVisitor(this) - .ContainsOuterReference(innerSelectExpression); - if (containsReferenceToOuter) - { - return null; + default: + throw new InvalidOperationException(value.GetType().ToString()); + } } - var identifierFromParent = _identifier; - if (innerSelectExpression.Tables.LastOrDefault(e => e is InnerJoinExpression) is InnerJoinExpression - collectionInnerJoinExpression - && collectionInnerJoinExpression.Table is TableExpressionBase collectionTableExpressionBase) + if (remappingRequired) { - // This computes true parent identifier count for correlation. - // The last inner joined table in innerSelectExpression brings collection data. - // Further tables load additional data on the collection (hence uses outer pattern) - // So identifier not coming from there (which would be at the start only) are for correlation with parent. - // Parent can have additional identifier if a owned reference was expanded. - var actualParentIdentifierCount = innerSelectExpression._identifier - .TakeWhile(e => !ReferenceEquals(e.Column.Table, collectionTableExpressionBase)) - .Count(); - identifierFromParent = _identifier.Take(actualParentIdentifierCount).ToList(); + shaperExpression = new ClientProjectionRemappingExpressionVisitor(clientProjectionIndexMap).Visit(shaperExpression); } - var parentIdentifier = GetIdentifierAccessor(this, identifierFromParent).Item1; - // We apply projection here because the outer level visitor does not visit this. - innerSelectExpression.ApplyProjection(); + _clientProjections = newClientProjections; + _aliasForClientProjections.Clear(); + return shaperExpression; - for (var i = 0; i < identifierFromParent.Count; i++) + Expression CopyProjectionToOuter(SelectExpression innerSelectExpression, Expression innerShaperExpression) { - AppendOrdering(new OrderingExpression(identifierFromParent[i].Column, ascending: true)); - } - - // Copy over ordering from previous collections - var innerOrderingExpressions = new List(); - for (var i = 0; i < innerSelectExpression.Tables.Count; i++) - { - var table = innerSelectExpression.Tables[i]; - if (table is InnerJoinExpression collectionJoinExpression - && collectionJoinExpression.Table is SelectExpression collectionSelectExpression - && collectionSelectExpression.Predicate != null - && collectionSelectExpression.Tables.Count == 1 - && collectionSelectExpression.Tables[0] is SelectExpression rowNumberSubquery - && rowNumberSubquery.Projection.Select(pe => pe.Expression) - .OfType().SingleOrDefault() is RowNumberExpression rowNumberExpression) + var projectionIndexMap = new int[innerSelectExpression._projection.Count]; + var innerTableReferenceExpression = _tableReferences[^1]; + for (var j = 0; j < projectionIndexMap.Length; j++) { - var collectionSelectExpressionTableReference = innerSelectExpression._tableReferences[i]; - var rowNumberSubqueryTableReference = collectionSelectExpression._tableReferences.Single(); - foreach (var partition in rowNumberExpression.Partitions) - { - innerOrderingExpressions.Add( - new OrderingExpression( - collectionSelectExpression.GenerateOuterColumn( - collectionSelectExpressionTableReference, - rowNumberSubquery.GenerateOuterColumn(rowNumberSubqueryTableReference, partition)), - ascending: true)); - } - - foreach (var ordering in rowNumberExpression.Orderings) - { - innerOrderingExpressions.Add( - new OrderingExpression( - collectionSelectExpression.GenerateOuterColumn( - collectionSelectExpressionTableReference, - rowNumberSubquery.GenerateOuterColumn(rowNumberSubqueryTableReference, ordering.Expression)), - ordering.IsAscending)); - } + var projection = MakeNullable(innerSelectExpression._projection[j].Expression, nullable: true); + var index = AddToProjection(projection); + projectionIndexMap[j] = index; } - if (table is CrossApplyExpression collectionApplyExpression - && collectionApplyExpression.Table is SelectExpression collectionSelectExpression2 - && collectionSelectExpression2.Orderings.Count > 0) + var indexMap = new int[innerSelectExpression._clientProjections.Count]; + for (var j = 0; j < indexMap.Length; j++) { - var collectionSelectExpressionTableReference = innerSelectExpression._tableReferences[i]; - foreach (var ordering in collectionSelectExpression2.Orderings) + var projection = innerSelectExpression._clientProjections[j]; + if (projection is not ConstantExpression projectionConstant) + { + throw new InvalidOperationException(); + } + var constantValue = projectionConstant.Value; + ConstantExpression remappedConstant; + if (constantValue is Dictionary entityDictionary) { - if (innerSelectExpression._identifier.Any(e => e.Column.Equals(ordering.Expression))) + var newDictionary = new Dictionary(entityDictionary.Count); + foreach (var kvp in entityDictionary) { - continue; + newDictionary[kvp.Key] = projectionIndexMap[kvp.Value]; } - - innerOrderingExpressions.Add( - new OrderingExpression( - collectionSelectExpression2.GenerateOuterColumn(collectionSelectExpressionTableReference, ordering.Expression), - ordering.IsAscending)); + remappedConstant = Constant(newDictionary); } - } - } - - var (childIdentifier, childIdentifierValueComparers) = GetIdentifierAccessor( - innerSelectExpression, innerSelectExpression._identifier.Take(identifierFromParent.Count)); - - var identifierIndex = 0; - var orderingIndex = 0; - for (var i = 0; i < Orderings.Count; i++) - { - var outerOrdering = Orderings[i]; - if (identifierIndex < identifierFromParent.Count - && outerOrdering.Expression.Equals(identifierFromParent[identifierIndex].Column)) - { - innerSelectExpression.AppendOrdering( - new OrderingExpression( - innerSelectExpression._identifier[identifierIndex].Column, ascending: true)); - identifierIndex++; - } - else - { - if (i < innerSelectExpression.Orderings.Count) + else if (constantValue is int indexValue) { - continue; + remappedConstant = Constant(projectionIndexMap[indexValue]); } - - innerSelectExpression.AppendOrdering(innerOrderingExpressions[orderingIndex]); - orderingIndex++; + else + { + throw new InvalidOperationException(); + } + newClientProjections.Add(remappedConstant); + indexMap[j] = newClientProjections.Count - 1; } - } - foreach (var orderingExpression in innerOrderingExpressions.Skip(orderingIndex)) - { - innerSelectExpression.AppendOrdering(orderingExpression); - } + innerSelectExpression._clientProjections.Clear(); + innerSelectExpression._aliasForClientProjections.Clear(); + innerShaperExpression = new ProjectionIndexRemappingExpressionVisitor(this, indexMap).Visit(innerShaperExpression); + innerShaperExpression = new EntityShaperNullableMarkingExpressionVisitor().Visit(innerShaperExpression); - return new RelationalSplitCollectionShaperExpression( - collectionId, parentIdentifier, childIdentifier, childIdentifierValueComparers, - innerSelectExpression, innerShaper, navigation, elementType); + return innerShaperExpression; + } } else { - var parentIdentifierList = _identifier.Except(_childIdentifiers, _identifierComparer).ToList(); - - var (parentIdentifier, parentIdentifierValueComparers) = GetIdentifierAccessor(this, parentIdentifierList); - var (outerIdentifier, outerIdentifierValueComparers) = GetIdentifierAccessor(this, _identifier); - - if (collectionIndex == 0) + var result = new Dictionary(_projectionMapping.Count); + foreach (var keyValuePair in _projectionMapping) { - foreach (var identifier in _identifier) - { - AppendOrdering(new OrderingExpression(identifier.Column, ascending: true)); - } + result[keyValuePair.Key] = keyValuePair.Value is EntityProjectionExpression entityProjection + ? AddEntityProjection(entityProjection) + : Constant(AddToProjection((SqlExpression)keyValuePair.Value, keyValuePair.Key.Last?.Name)); } - AddJoin(JoinType.OuterApply, ref innerSelectExpression); - var innerOrderingExpressions = new List(); - var joinedTable = innerSelectExpression.Tables.Single(); - if (joinedTable is SelectExpression collectionSelectExpression - && collectionSelectExpression.Predicate != null - && collectionSelectExpression.Tables.Count == 1 - && collectionSelectExpression.Tables[0] is SelectExpression rowNumberSubquery - && rowNumberSubquery.Projection.Select(pe => pe.Expression) - .OfType().SingleOrDefault() is RowNumberExpression rowNumberExpression) - { - var collectionSelectExpressionTableReference = innerSelectExpression._tableReferences.Single(); - var rowNumberSubqueryTableReference = collectionSelectExpression._tableReferences.Single(); - foreach (var partition in rowNumberExpression.Partitions) - { - innerOrderingExpressions.Add( - new OrderingExpression( - collectionSelectExpression.GenerateOuterColumn( - collectionSelectExpressionTableReference, - rowNumberSubquery.GenerateOuterColumn(rowNumberSubqueryTableReference, partition)), - ascending: true)); - } + _projectionMapping.Clear(); + _projectionMapping = result; - foreach (var ordering in rowNumberExpression.Orderings) - { - innerOrderingExpressions.Add( - new OrderingExpression( - collectionSelectExpression.GenerateOuterColumn( - collectionSelectExpressionTableReference, - rowNumberSubquery.GenerateOuterColumn(rowNumberSubqueryTableReference, ordering.Expression)), - ordering.IsAscending)); - } - } - else if (joinedTable is SelectExpression collectionSelectExpression2 - && collectionSelectExpression2.Orderings.Count > 0) - { - var collectionSelectExpressionTableReference = innerSelectExpression._tableReferences.Single(); - foreach (var ordering in collectionSelectExpression2.Orderings) - { - if (innerSelectExpression._identifier.Any(e => e.Column.Equals(ordering.Expression))) - { - continue; - } + return shaperExpression; + } - innerOrderingExpressions.Add( - new OrderingExpression( - collectionSelectExpression2.GenerateOuterColumn(collectionSelectExpressionTableReference, ordering.Expression), - ordering.IsAscending)); - } - } - else + ConstantExpression AddEntityProjection(EntityProjectionExpression entityProjectionExpression) + { + var dictionary = new Dictionary(); + foreach (var property in GetAllPropertiesInHierarchy(entityProjectionExpression.EntityType)) { - innerOrderingExpressions.AddRange(innerSelectExpression.Orderings); + dictionary[property] = AddToProjection(entityProjectionExpression.BindProperty(property), null); } - foreach (var ordering in innerOrderingExpressions) + if (entityProjectionExpression.DiscriminatorExpression != null) { - AppendOrdering(ordering.Update(MakeNullable(ordering.Expression, nullable: true))); + AddToProjection(entityProjectionExpression.DiscriminatorExpression, _discriminatorColumnAlias); } - var remapper = new ProjectionBindingExpressionRemappingExpressionVisitor(this); - // Outer projection are already populated - if (innerSelectExpression.Projection.Count > 0) - { - // Add inner to projection and update indexes - var indexMap = new int[innerSelectExpression.Projection.Count]; - for (var i = 0; i < innerSelectExpression.Projection.Count; i++) - { - var projectionToAdd = innerSelectExpression.Projection[i].Expression; - projectionToAdd = MakeNullable(projectionToAdd, nullable: true); - indexMap[i] = AddToProjection(projectionToAdd); - } + return Constant(dictionary); + } + } - innerShaper = remapper.RemapIndex(innerShaper, indexMap); - } - else - { - // Apply inner projection mapping and convert projection member binding to indexes - var mapping = ApplyProjectionMapping(innerSelectExpression._projectionMapping, makeNullable: true); - innerShaper = remapper.RemapProjectionMember(innerShaper, mapping); - } + /// + /// Clears all existing projections. + /// + [Obsolete("Use ReplaceProjection with empty list to clear out projections and associated bindings.")] + public void ClearProjection() + { + throw new InvalidOperationException("Clear Projection should clear the client/server projections"); + } - innerShaper = new EntityShaperNullableMarkingExpressionVisitor().Visit(innerShaper); + /// + /// Replaces current projection mapping with a new one to change what is being projected out from this . + /// + /// A new projection mapping. + [Obsolete("Use ReplaceProjection method instead.")] + public void ReplaceProjectionMapping(IDictionary projectionMapping) + { + Check.NotNull(projectionMapping, nameof(projectionMapping)); - var (selfIdentifier, selfIdentifierValueComparers) = GetIdentifierAccessor( - this, - innerSelectExpression._identifier - .Except(innerSelectExpression._childIdentifiers, _identifierComparer) - .Select(e => (e.Column.MakeNullable(), e.Comparer))); + _projectionMapping.Clear(); + foreach (var kvp in projectionMapping) + { + _projectionMapping[kvp.Key] = kvp.Value; + } + } - foreach (var identifier in innerSelectExpression._identifier) - { - var updatedColumn = identifier.Column.MakeNullable(); - _childIdentifiers.Add((updatedColumn, identifier.Comparer)); - AppendOrdering(new OrderingExpression(updatedColumn, ascending: true)); - } + /// + /// Replaces current projection mapping with a new one to change what is being projected out from this . + /// + /// A new projection mapping. + public void ReplaceProjection(IReadOnlyDictionary projectionMapping) + { + _projectionMapping.Clear(); + foreach (var kvp in projectionMapping) + { + var expression = kvp.Value; + Check.DebugAssert( + expression is SqlExpression + || expression is EntityProjectionExpression, + "Invalid operation in the projection."); + _projectionMapping[kvp.Key] = expression; + } + } + + /// + /// Replaces current projection mapping with a new one to change what is being projected out from this . + /// + /// A new projection mapping. + public void ReplaceProjection(IReadOnlyList clientProjections) + { + _projectionMapping.Clear(); + _clientProjections.Clear(); + _aliasForClientProjections.Clear(); + foreach (var expression in clientProjections) + { + Check.DebugAssert( + expression is SqlExpression + || expression is EntityProjectionExpression + || expression is ShapedQueryExpression, + "Invalid operation in the projection."); + _clientProjections.Add(expression); + _aliasForClientProjections.Add(null); + } + } + + /// + /// Gets the projection mapped to the given . + /// + /// A projection member to search in the mapping. + /// The mapped projection for given projection member. + [Obsolete("Use GetProjection method using ProjectionBindingExpression to get mapped projection.")] + public Expression GetMappedProjection(ProjectionMember projectionMember) + { + Check.NotNull(projectionMember, nameof(projectionMember)); + + return _projectionMapping[projectionMember]; + } + + /// + /// Gets the projection mapped to the given . + /// + /// A projection binding to search. + /// The mapped projection for given projection binding. + public Expression GetProjection(ProjectionBindingExpression projectionBindingExpression) + => projectionBindingExpression.ProjectionMember is ProjectionMember projectionMember + ? _projectionMapping[projectionMember] + : _clientProjections[projectionBindingExpression.Index!.Value]; - var result = new RelationalCollectionShaperExpression( - collectionId, parentIdentifier, outerIdentifier, selfIdentifier, - parentIdentifierValueComparers, outerIdentifierValueComparers, selfIdentifierValueComparers, - innerShaper, navigation, elementType); + /// + /// Adds given to the projection. + /// + /// An expression to add. + /// An int value indicating the index at which the expression was added in the projection list. + public int AddToProjection(SqlExpression sqlExpression) + { + Check.NotNull(sqlExpression, nameof(sqlExpression)); + + return AddToProjection(sqlExpression, null); + } - return result; + private int AddToProjection(SqlExpression sqlExpression, string? alias, bool assignUniqueTableAlias = true) + { + var existingIndex = _projection.FindIndex(pe => pe.Expression.Equals(sqlExpression)); + if (existingIndex != -1) + { + return existingIndex; } - static (Expression, IReadOnlyList) GetIdentifierAccessor( - SelectExpression selectExpression, - IEnumerable<(ColumnExpression Column, ValueComparer Comparer)> identifyingProjection) + var baseAlias = !string.IsNullOrEmpty(alias) + ? alias + : (sqlExpression as ColumnExpression)?.Name; + if (Alias != null) { - var updatedExpressions = new List(); - var comparers = new List(); - foreach (var keyExpression in identifyingProjection) - { - var index = selectExpression.AddToProjection(keyExpression.Column); - var projectionBindingExpression = new ProjectionBindingExpression( - selectExpression, index, keyExpression.Column.Type.MakeNullable()); + baseAlias ??= "c"; + var counter = 0; - updatedExpressions.Add( - projectionBindingExpression.Type.IsValueType - ? Convert(projectionBindingExpression, typeof(object)) - : (Expression)projectionBindingExpression); - comparers.Add(keyExpression.Comparer); + var currentAlias = baseAlias; + while (_projection.Any(pe => string.Equals(pe.Alias, currentAlias, StringComparison.OrdinalIgnoreCase))) + { + currentAlias = $"{baseAlias}{counter++}"; } - return (NewArrayInit(typeof(object), updatedExpressions), comparers); + baseAlias = currentAlias; + } + + if (assignUniqueTableAlias) + { + sqlExpression = AssignUniqueAliases(sqlExpression); } + _projection.Add(new ProjectionExpression(sqlExpression, baseAlias ?? "")); + + return _projection.Count - 1; } /// @@ -1242,10 +1341,8 @@ private void ApplySetOperation(SetOperationType setOperationType, SelectExpressi _tables.Add(setExpression); _tableReferences.Add(tableReferenceExpression); - if (_projection.Any() - || select2._projection.Any() - || _pendingCollections.Any() - || select2._pendingCollections.Any()) + if (_clientProjections.Count > 0 + || select2._clientProjections.Count > 0) { throw new InvalidOperationException(RelationalStrings.SetOperationsNotAllowedAfterClientEvaluation); } @@ -1599,8 +1696,7 @@ static TableReferenceExpression FindTableReference(SelectExpression selectExpres var tableReferenceExpression = FindTableReference(selectExpression, subquery); foreach (var item in subqueryPropertyExpressions) { - newPropertyExpressions[item.Key] = new ConcreteColumnExpression( - subquery.Projection[subquery.AddToProjection(item.Value)], tableReferenceExpression); + newPropertyExpressions[item.Key] = subquery.GenerateOuterColumn(tableReferenceExpression, item.Value); } return newPropertyExpressions; @@ -1644,15 +1740,13 @@ private Expression AddJoin( Expression innerShaper, SqlExpression? joinPredicate = null) { - var pendingCollectionOffset = _pendingCollections.Count; AddJoin(joinType, ref innerSelectExpression, joinPredicate); var transparentIdentifierType = TransparentIdentifierFactory.Create(outerShaper.Type, innerShaper.Type); var outerMemberInfo = transparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Outer"); var innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetRequiredDeclaredField("Inner"); - var outerClientEval = Projection.Count > 0; - var innerClientEval = innerSelectExpression.Projection.Count > 0; - var remapper = new ProjectionBindingExpressionRemappingExpressionVisitor(this); + var outerClientEval = _clientProjections.Count > 0; + var innerClientEval = innerSelectExpression._clientProjections.Count > 0; var innerNullable = joinType == JoinType.LeftJoin || joinType == JoinType.OuterApply; if (outerClientEval) @@ -1661,21 +1755,25 @@ private Expression AddJoin( if (innerClientEval) { // Add inner to projection and update indexes - var indexMap = new int[innerSelectExpression.Projection.Count]; - for (var i = 0; i < innerSelectExpression.Projection.Count; i++) + var indexMap = new int[innerSelectExpression._clientProjections.Count]; + for (var i = 0; i < innerSelectExpression._clientProjections.Count; i++) { - var projectionToAdd = innerSelectExpression.Projection[i].Expression; + var projectionToAdd = innerSelectExpression._clientProjections[i]; projectionToAdd = MakeNullable(projectionToAdd, innerNullable); - indexMap[i] = AddToProjection(projectionToAdd); + _clientProjections.Add(projectionToAdd); + _aliasForClientProjections.Add(innerSelectExpression._aliasForClientProjections[i]); + indexMap[i] = _clientProjections.Count - 1; } + innerSelectExpression._clientProjections.Clear(); + innerSelectExpression._aliasForClientProjections.Clear(); - innerShaper = remapper.RemapIndex(innerShaper, indexMap, pendingCollectionOffset); + innerShaper = new ProjectionIndexRemappingExpressionVisitor(this, indexMap).Visit(innerShaper); } else { // Apply inner projection mapping and convert projection member binding to indexes - var mapping = ApplyProjectionMapping(innerSelectExpression._projectionMapping, innerNullable); - innerShaper = remapper.RemapProjectionMember(innerShaper, mapping, pendingCollectionOffset); + var mapping = ConvertProjectionMappingToClientProjections(innerSelectExpression._projectionMapping, innerNullable); + innerShaper = new ProjectionMemberToIndexConvertingExpressionVisitor(this, mapping).Visit(innerShaper); } } else @@ -1684,23 +1782,27 @@ private Expression AddJoin( if (innerClientEval) { // Since inner proojections are populated, we need to populate outer also - var mapping = ApplyProjectionMapping(_projectionMapping); - outerShaper = remapper.RemapProjectionMember(outerShaper, mapping); + var mapping = ConvertProjectionMappingToClientProjections(_projectionMapping); + outerShaper = new ProjectionMemberToIndexConvertingExpressionVisitor(this, mapping).Visit(outerShaper); - var indexMap = new int[innerSelectExpression.Projection.Count]; - for (var i = 0; i < innerSelectExpression.Projection.Count; i++) + var indexMap = new int[innerSelectExpression._clientProjections.Count]; + for (var i = 0; i < innerSelectExpression._clientProjections.Count; i++) { - var projectionToAdd = innerSelectExpression.Projection[i].Expression; + var projectionToAdd = innerSelectExpression._clientProjections[i]; projectionToAdd = MakeNullable(projectionToAdd, innerNullable); - indexMap[i] = AddToProjection(projectionToAdd); + _clientProjections.Add(projectionToAdd); + _aliasForClientProjections.Add(innerSelectExpression._aliasForClientProjections[i]); + indexMap[i] = _clientProjections.Count - 1; } + innerSelectExpression._clientProjections.Clear(); + innerSelectExpression._aliasForClientProjections.Clear(); - innerShaper = remapper.RemapIndex(innerShaper, indexMap, pendingCollectionOffset); + innerShaper = new ProjectionIndexRemappingExpressionVisitor(this, indexMap).Visit(innerShaper); } else { var projectionMapping = new Dictionary(); - var mapping = new Dictionary(); + var mapping = new Dictionary(); foreach (var projection in _projectionMapping) { @@ -1710,7 +1812,7 @@ private Expression AddJoin( projectionMapping[remappedProjectionMember] = projection.Value; } - outerShaper = remapper.RemapProjectionMember(outerShaper, mapping); + outerShaper = new ProjectionMemberRemappingExpressionVisitor(this, mapping).Visit(outerShaper); mapping.Clear(); foreach (var projection in innerSelectExpression._projectionMapping) @@ -1723,7 +1825,7 @@ private Expression AddJoin( projectionMapping[remappedProjectionMember] = projectionToAdd; } - innerShaper = remapper.RemapProjectionMember(innerShaper, mapping, pendingCollectionOffset); + innerShaper = new ProjectionMemberRemappingExpressionVisitor(this, mapping).Visit(innerShaper); _projectionMapping = projectionMapping; innerSelectExpression._projectionMapping.Clear(); } @@ -1882,10 +1984,6 @@ private void AddJoin( } var innerTable = innerSelectExpression.Tables.Single(); - // Copy over pending collection if in join else that info would be lost. - // The calling method is supposed to take care of remapping the shaper so that copied over collection indexes match. - _pendingCollections.AddRange(innerSelectExpression._pendingCollections); - innerSelectExpression._pendingCollections.Clear(); var joinTable = joinType switch { @@ -2443,6 +2541,7 @@ private SqlRemappingVisitor PushdownIntoSubqueryInternal() Offset = Offset, Limit = Limit }; + subquery._usedAliases = _usedAliases; _tables.Clear(); _tableReferences.Clear(); _groupBy.Clear(); @@ -2462,38 +2561,73 @@ private SqlRemappingVisitor PushdownIntoSubqueryInternal() var projectionMap = new Dictionary(ReferenceEqualityComparer.Instance); - // Projection would be present for client eval. - if (_projection.Any()) + if (_projection.Count > 0) { var projections = _projection.ToList(); _projection.Clear(); foreach (var projection in projections) { - var outerColumn = subquery.GenerateOuterColumn(subqueryTableReferenceExpression, projection.Expression, projection.Alias); - AddToProjection(outerColumn); + // Since these projections are already added, they have unique table alias already. + // The only new alias added was for "t" which we already made unique at the start of the method. + var outerColumn = subquery.GenerateOuterColumn( + subqueryTableReferenceExpression, projection.Expression, projection.Alias, assignUniqueTableAlias: false); + AddToProjection(outerColumn, null); projectionMap[projection.Expression] = outerColumn; } } - foreach (var mapping in _projectionMapping.ToList()) + var nestedQueryInProjection = false; + // Projection would be present for client eval case + if (_clientProjections.Count > 0) { - // If projectionMapping's value is ConstantExpression then projection has already been applied - // And captured in _projections above so we don't need to process this. - if (mapping.Value is ConstantExpression) + for (var i = 0; i < _clientProjections.Count; i++) { - break; - } + var item = _clientProjections[i]; + // If item's value is ConstantExpression then projection has already been applied + if (item is ConstantExpression) + { + break; + } - if (mapping.Value is EntityProjectionExpression entityProjection) - { - _projectionMapping[mapping.Key] = LiftEntityProjectionFromSubquery(entityProjection); + if (item is EntityProjectionExpression entityProjection) + { + _clientProjections[i] = LiftEntityProjectionFromSubquery(entityProjection); + } + else if (item is SqlExpression sqlExpression) + { + var alias = _aliasForClientProjections[i]; + var outerColumn = subquery.GenerateOuterColumn(subqueryTableReferenceExpression, sqlExpression, alias); + projectionMap[sqlExpression] = outerColumn; + _clientProjections[i] = outerColumn; + _aliasForClientProjections[i] = null; + } + else + { + nestedQueryInProjection = true; + } } - else + } + else + { + foreach (var mapping in _projectionMapping.ToList()) { - var innerColumn = (SqlExpression)mapping.Value; - var outerColumn = subquery.GenerateOuterColumn(subqueryTableReferenceExpression, innerColumn, mapping.Key.Last?.Name); - projectionMap[innerColumn] = outerColumn; - _projectionMapping[mapping.Key] = outerColumn; + // If projectionMapping's value is ConstantExpression then projection has already been applied + if (mapping.Value is ConstantExpression) + { + break; + } + + if (mapping.Value is EntityProjectionExpression entityProjection) + { + _projectionMapping[mapping.Key] = LiftEntityProjectionFromSubquery(entityProjection); + } + else + { + var innerColumn = (SqlExpression)mapping.Value; + var outerColumn = subquery.GenerateOuterColumn(subqueryTableReferenceExpression, innerColumn, mapping.Key.Last?.Name); + projectionMap[innerColumn] = outerColumn; + _projectionMapping[mapping.Key] = outerColumn; + } } } @@ -2539,7 +2673,8 @@ private SqlRemappingVisitor PushdownIntoSubqueryInternal() else if (!IsDistinct && GroupBy.Count == 0 || GroupBy.Contains(orderingExpression)) { - _orderings.Add(ordering.Update(subquery.GenerateOuterColumn(subqueryTableReferenceExpression, orderingExpression))); + _orderings.Add(ordering.Update(subquery.GenerateOuterColumn( + subqueryTableReferenceExpression, orderingExpression, assignUniqueTableAlias: false))); } else { @@ -2564,13 +2699,16 @@ private SqlRemappingVisitor PushdownIntoSubqueryInternal() var sqlRemappingVisitor = new SqlRemappingVisitor(projectionMap, subquery, subqueryTableReferenceExpression); tableReferenceUpdatingExpressionVisitor.Visit(subquery); - var pendingCollections = _pendingCollections.ToList(); - _pendingCollections.Clear(); - foreach (var collection in pendingCollections) + if (nestedQueryInProjection) { - // We need to update tableReferences first in case the collection has correlated element to this select expression - _pendingCollections.Add(sqlRemappingVisitor.Remap( - (SelectExpression)tableReferenceUpdatingExpressionVisitor.Visit(collection)!)); + for (var i = 0; i < _clientProjections.Count; i++) + { + if (_clientProjections[i] is ShapedQueryExpression shapedQueryExpression) + { + _clientProjections[i] = shapedQueryExpression.Update( + sqlRemappingVisitor.Visit(shapedQueryExpression.QueryExpression), shapedQueryExpression.ShaperExpression); + } + } } return sqlRemappingVisitor; @@ -2702,12 +2840,12 @@ private SelectExpression Prune(IReadOnlyCollection? referencedColumns = return this; } - private Dictionary ApplyProjectionMapping( + private Dictionary ConvertProjectionMappingToClientProjections( Dictionary projectionMapping, bool makeNullable = false) { - var mapping = new Dictionary(); - var entityProjectionCache = new Dictionary>(ReferenceEqualityComparer.Instance); + var mapping = new Dictionary(); + var entityProjectionCache = new Dictionary(ReferenceEqualityComparer.Instance); foreach (var projection in projectionMapping) { var projectionMember = projection.Key; @@ -2722,7 +2860,9 @@ private Dictionary ApplyProjectionMapping( { entityProjection = entityProjection.MakeNullable(); } - value = AddToProjection(entityProjection); + _clientProjections.Add(entityProjection); + _aliasForClientProjections.Add(null); + value = _clientProjections.Count - 1; entityProjectionCache[entityProjectionToCache] = value; } @@ -2731,7 +2871,14 @@ private Dictionary ApplyProjectionMapping( else { projectionToAdd = MakeNullable(projectionToAdd, makeNullable); - mapping[projectionMember] = AddToProjection((SqlExpression)projectionToAdd, projectionMember.Last?.Name); + var existingIndex = _clientProjections.FindIndex(e => e.Equals(projectionToAdd)); + if (existingIndex == -1) + { + _clientProjections.Add(projectionToAdd); + _aliasForClientProjections.Add(projectionMember.Last?.Name); + existingIndex = _clientProjections.Count - 1; + } + mapping[projectionMember] = existingIndex; } } @@ -2776,9 +2923,11 @@ private static ConcreteColumnExpression CreateColumnExpression( => new(property, table.FindColumn(property)!, tableExpression, nullable); private ConcreteColumnExpression GenerateOuterColumn( - TableReferenceExpression tableReferenceExpression, SqlExpression projection, string? alias = null) + TableReferenceExpression tableReferenceExpression, SqlExpression projection, string? alias = null, bool assignUniqueTableAlias = true) { - var index = AddToProjection(projection, alias); + // TODO: Add check if we can add projection in subquery to generate out column + // Subquery having Distinct or GroupBy can block it. + var index = AddToProjection(projection, alias, assignUniqueTableAlias); return new ConcreteColumnExpression(_projection[index], tableReferenceExpression); } @@ -2828,15 +2977,12 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) { Check.NotNull(visitor, nameof(visitor)); - // If there are pending collections, then do in-place mutation. - // Post translation we want not in place mutation so that cached SelectExpression inside relational command doesn't get mutated. - if (_pendingCollections.Any(e => e != null)) + if (_projection.Count == 0) { - if (Projection.Any()) + // If projection is not populated then we need to treat this as mutable object since it is not final yet. + if (_clientProjections.Count > 0) { - var projections = _projection.ToList(); - _projection.Clear(); - _projection.AddRange(projections.Select(e => (ProjectionExpression)visitor.Visit(e))); + VisitList(_clientProjections, inPlace: true, out _); } else { @@ -2851,209 +2997,197 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) _projectionMapping = projectionMapping; } - // We cannot erase _tables before visiting all because joinPredicate may reference them which breaks referential integrity - var visitedTables = new List(); - visitedTables.AddRange(_tables.Select(e => (TableExpressionBase)visitor.Visit(e))); + var newTables = VisitList(_tables, inPlace: true, out var tablesChanged); Check.DebugAssert( - visitedTables.Select(e => GetAliasFromTableExpressionBase(e)).SequenceEqual(_tableReferences.Select(e => e.Alias)), - "Aliases of Table/TableReferences must match after visit."); - _tables.Clear(); - _tables.AddRange(visitedTables); - + !tablesChanged + || newTables.Select(e => GetAliasFromTableExpressionBase(e)).SequenceEqual(_tableReferences.Select(e => e.Alias)), + "Alias of updated tables must match the old tables."); Predicate = (SqlExpression?)visitor.Visit(Predicate); - var groupBy = _groupBy.ToList(); - _groupBy.Clear(); - _groupBy.AddRange( - groupBy.Select(e => (SqlExpression)visitor.Visit(e)) - .Where(e => !(e is SqlConstantExpression || e is SqlParameterExpression))); + var newGroupBy = _groupBy; + for (var i = 0; i < _groupBy.Count; i++) + { + var groupingKey = _groupBy[i]; + var newGroupingKey = (SqlExpression)visitor.Visit(groupingKey); + if (newGroupingKey != groupingKey + || newGroupingKey is SqlConstantExpression + || newGroupingKey is SqlParameterExpression) + { + if (newGroupBy == _groupBy) + { + newGroupBy = new List(_groupBy.Count); + for (var j = 0; j < i; j++) + { + newGroupBy.Add(_groupBy[j]); + } + } + } + + if (newGroupBy != _groupBy + && !(newGroupingKey is SqlConstantExpression + || newGroupingKey is SqlParameterExpression)) + { + newGroupBy.Add(newGroupingKey); + } + } + if (newGroupBy != _groupBy) + { + _groupBy.Clear(); + _groupBy.AddRange(newGroupBy); + } Having = (SqlExpression?)visitor.Visit(Having); - var orderings = _orderings.ToList(); - _orderings.Clear(); - _orderings.AddRange(orderings.Select(e => e.Update((SqlExpression)visitor.Visit(e.Expression)))); + VisitList(_orderings, inPlace: true, out _); Offset = (SqlExpression?)visitor.Visit(Offset); Limit = (SqlExpression?)visitor.Visit(Limit); - if (visitor is SqlRemappingVisitor) - { - // We have to traverse pending collections for remapping so that columns from outer are updated. - var pendingCollections = _pendingCollections.ToList(); - _pendingCollections.Clear(); - _pendingCollections.AddRange(pendingCollections.Select(e => (SelectExpression)visitor.Visit(e)!)); - } - return this; } + else + { + // If projection is populated then + // Either this SelectExpression is not bound to a shaped query expression + // Or it is post-translation phase where it will update the shaped query expression + // So we will treat it as immutable + var newProjections = VisitList(_projection, inPlace: false, out var changed); - var changed = false; + // We don't need to visit _clientProjection/_projectionMapping here + // because once projection is populated both of them contains expressions for client binding rather than a server query. - var newProjections = _projection; - var newProjectionMapping = _projectionMapping; - if (_projection.Any()) - { - for (var i = 0; i < _projection.Count; i++) + var newTables = VisitList(_tables, inPlace: false, out var tablesChanged); + changed |= tablesChanged; + + Check.DebugAssert( + !tablesChanged + || newTables.Select(e => GetAliasFromTableExpressionBase(e)).SequenceEqual(_tableReferences.Select(e => e.Alias)), + "Alias of updated tables must match the old tables."); + + var predicate = (SqlExpression?)visitor.Visit(Predicate); + changed |= predicate != Predicate; + + var newGroupBy = _groupBy; + for (var i = 0; i < _groupBy.Count; i++) { - var item = _projection[i]; - var projection = (ProjectionExpression)visitor.Visit(item); - if (projection != item - && newProjections == _projection) + var groupingKey = _groupBy[i]; + var newGroupingKey = (SqlExpression)visitor.Visit(groupingKey); + if (newGroupingKey != groupingKey + || newGroupingKey is SqlConstantExpression + || newGroupingKey is SqlParameterExpression) { - newProjections = new List(_projection.Count); - for (var j = 0; j < i; j++) + if (newGroupBy == _groupBy) { - newProjections.Add(_projection[j]); + newGroupBy = new List(_groupBy.Count); + for (var j = 0; j < i; j++) + { + newGroupBy.Add(_groupBy[j]); + } } changed = true; } - if (newProjections != _projection) + if (newGroupBy != _groupBy + && !(newGroupingKey is SqlConstantExpression + || newGroupingKey is SqlParameterExpression)) { - newProjections.Add(projection); + newGroupBy.Add(newGroupingKey); } } - } - else - { - foreach (var mapping in _projectionMapping) - { - var newProjection = visitor.Visit(mapping.Value); - if (newProjection != mapping.Value - && newProjectionMapping == _projectionMapping) - { - newProjectionMapping = new Dictionary(_projectionMapping); - changed = true; - } - if (newProjectionMapping != _projectionMapping) - { - newProjectionMapping[mapping.Key] = newProjection; - } - } - } + var havingExpression = (SqlExpression?)visitor.Visit(Having); + changed |= havingExpression != Having; - var newTables = _tables; - for (var i = 0; i < _tables.Count; i++) - { - var table = _tables[i]; - var newTable = (TableExpressionBase)visitor.Visit(table); - Check.DebugAssert(GetAliasFromTableExpressionBase(newTable) == _tableReferences[i].Alias, - "Alias of updated table must match the old table."); - if (newTable != table - && newTables == _tables) + var newOrderings = VisitList(_orderings, inPlace: false, out var orderingChanged); + changed |= orderingChanged; + + var offset = (SqlExpression?)visitor.Visit(Offset); + changed |= offset != Offset; + + var limit = (SqlExpression?)visitor.Visit(Limit); + changed |= limit != Limit; + + if (changed) { - newTables = new List(_tables.Count); - for (var j = 0; j < i; j++) + var newTableReferences = _tableReferences.ToList(); + var newSelectExpression = new SelectExpression(Alias, newProjections, newTables, newTableReferences, newGroupBy, newOrderings) + { + _clientProjections = _clientProjections, + _projectionMapping = _projectionMapping, + Predicate = predicate, + Having = havingExpression, + Offset = offset, + Limit = limit, + IsDistinct = IsDistinct, + Tags = Tags + }; + + newSelectExpression._identifier.AddRange(_identifier); + newSelectExpression._identifier.AddRange(_childIdentifiers); + + // Remap tableReferences in new select expression + foreach (var tableReference in newTableReferences) { - newTables.Add(_tables[j]); + tableReference.UpdateTableReference(this, newSelectExpression); } - changed = true; - } + var tableReferenceUpdatingExpressionVisitor = new TableReferenceUpdatingExpressionVisitor(this, newSelectExpression); + tableReferenceUpdatingExpressionVisitor.Visit(newSelectExpression); - if (newTables != _tables) - { - newTables.Add(newTable); + return newSelectExpression; } - } - var predicate = (SqlExpression?)visitor.Visit(Predicate); - changed |= predicate != Predicate; + return this; + } - var newGroupBy = _groupBy; - for (var i = 0; i < _groupBy.Count; i++) + List VisitList(List list, bool inPlace, out bool changed) + where T : Expression { - var groupingKey = _groupBy[i]; - var newGroupingKey = (SqlExpression)visitor.Visit(groupingKey); - if (newGroupingKey != groupingKey - || newGroupingKey is SqlConstantExpression - || newGroupingKey is SqlParameterExpression) + changed = false; + var newList = list; + for (var i = 0; i < list.Count; i++) { - if (newGroupBy == _groupBy) + var item = list[i]; + Expression newItem; + if (item is ShapedQueryExpression shapedQueryExpression) + { + newItem = shapedQueryExpression.Update( + visitor.Visit(shapedQueryExpression.QueryExpression), shapedQueryExpression.ShaperExpression); + } + else + { + newItem = visitor.Visit(item); + } + if (newItem != item + && newList == list) { - newGroupBy = new List(_groupBy.Count); + newList = new List(list.Count); for (var j = 0; j < i; j++) { - newGroupBy.Add(_groupBy[j]); + newList.Add(list[j]); } - } - changed = true; - } - - if (newGroupBy != _groupBy - && !(newGroupingKey is SqlConstantExpression - || newGroupingKey is SqlParameterExpression)) - { - newGroupBy.Add(newGroupingKey); - } - } - - var havingExpression = (SqlExpression?)visitor.Visit(Having); - changed |= havingExpression != Having; + changed = true; + } - var newOrderings = _orderings; - for (var i = 0; i < _orderings.Count; i++) - { - var ordering = _orderings[i]; - var newOrdering = (OrderingExpression)visitor.Visit(ordering); - if (newOrdering != ordering - && newOrderings == _orderings) - { - newOrderings = new List(_orderings.Count); - for (var j = 0; j < i; j++) + if (newList != list) { - newOrderings.Add(_orderings[j]); + newList.Add((T)newItem); } - - changed = true; } - if (newOrderings != _orderings) + if (inPlace + && changed) { - newOrderings.Add(newOrdering); - } - } - - var offset = (SqlExpression?)visitor.Visit(Offset); - changed |= offset != Offset; - - var limit = (SqlExpression?)visitor.Visit(Limit); - changed |= limit != Limit; + list.Clear(); + list.AddRange(newList); - if (changed) - { - var newTableReferences = _tableReferences.ToList(); - var newSelectExpression = new SelectExpression(Alias, newProjections, newTables, newTableReferences, newGroupBy, newOrderings) - { - _projectionMapping = newProjectionMapping, - Predicate = predicate, - Having = havingExpression, - Offset = offset, - Limit = limit, - IsDistinct = IsDistinct, - Tags = Tags - }; - - newSelectExpression._identifier.AddRange(_identifier); - newSelectExpression._identifier.AddRange(_childIdentifiers); - - // Remap tableReferences in new select expression - foreach (var tableReference in newTableReferences) - { - tableReference.UpdateTableReference(this, newSelectExpression); + return list; } - var tableReferenceUpdatingExpressionVisitor = new TableReferenceUpdatingExpressionVisitor(this, newSelectExpression); - tableReferenceUpdatingExpressionVisitor.Visit(newSelectExpression); - - return newSelectExpression; + return newList; } - - return this; } /// @@ -3163,14 +3297,31 @@ protected override void Print(ExpressionPrinter expressionPrinter) { Check.NotNull(expressionPrinter, nameof(expressionPrinter)); - expressionPrinter.AppendLine("Projection Mapping:"); - using (expressionPrinter.Indent()) + if (_clientProjections.Count > 0) { - foreach (var projectionMappingEntry in _projectionMapping) + expressionPrinter.AppendLine("Client Projections:"); + using (expressionPrinter.Indent()) { - expressionPrinter.AppendLine(); - expressionPrinter.Append(projectionMappingEntry.Key + " -> "); - expressionPrinter.Visit(projectionMappingEntry.Value); + for (var i = 0; i < _clientProjections.Count; i++) + { + expressionPrinter.AppendLine(); + expressionPrinter.Append(i.ToString()).Append(" -> "); + expressionPrinter.Visit(_clientProjections[i]); + } + } + + } + else if (_projectionMapping.Count > 0) + { + expressionPrinter.AppendLine("Projection Mapping:"); + using (expressionPrinter.Indent()) + { + foreach (var projectionMappingEntry in _projectionMapping) + { + expressionPrinter.AppendLine(); + expressionPrinter.Append(projectionMappingEntry.Key.ToString()).Append(" -> "); + expressionPrinter.Visit(projectionMappingEntry.Value); + } } } @@ -3303,6 +3454,11 @@ public override int GetHashCode() hash.Add(projection); } + foreach (var projection in _clientProjections) + { + hash.Add(projection); + } + foreach (var projectionMapping in _projectionMapping) { hash.Add(projectionMapping.Key); diff --git a/test/EFCore.SqlServer.FunctionalTests/ManyToManyFieldsLoadSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/ManyToManyFieldsLoadSqlServerTest.cs index 2da10601d01..ca6ef361d44 100644 --- a/test/EFCore.SqlServer.FunctionalTests/ManyToManyFieldsLoadSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/ManyToManyFieldsLoadSqlServerTest.cs @@ -188,7 +188,7 @@ public override async Task Load_collection_using_Query_with_join(bool async) AssertSql( @"@__p_0='3' -SELECT [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId], [t0].[Id0], [t0].[CollectionInverseId], [t0].[Name0], [t0].[ReferenceInverseId], [e].[Id], [t].[EntityOneId], [t].[EntityTwoId], [t0].[Id], [t0].[EntityOneId], [t0].[EntityTwoId], [t2].[EntityOneId], [t2].[EntityTwoId], [t2].[Id], [t2].[Name] +SELECT [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId], [e].[Id], [t].[EntityOneId], [t].[EntityTwoId], [t0].[Id], [t0].[EntityOneId], [t0].[EntityTwoId], [t0].[Id0], [t2].[EntityOneId], [t2].[EntityTwoId], [t2].[Id], [t2].[Name], [t0].[CollectionInverseId], [t0].[Name0], [t0].[ReferenceInverseId] FROM [EntityOnes] AS [e] INNER JOIN ( SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[Name], [e1].[ReferenceInverseId], [e0].[EntityOneId], [e0].[EntityTwoId] diff --git a/test/EFCore.SqlServer.FunctionalTests/ManyToManyLoadSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/ManyToManyLoadSqlServerTest.cs index 9a292de6b39..aadca6b4648 100644 --- a/test/EFCore.SqlServer.FunctionalTests/ManyToManyLoadSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/ManyToManyLoadSqlServerTest.cs @@ -187,7 +187,7 @@ public override async Task Load_collection_using_Query_with_join(bool async) AssertSql( @"@__p_0='3' -SELECT [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId], [t0].[Id0], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name0], [t0].[ReferenceInverseId], [e].[Id], [t].[EntityOneId], [t].[EntityTwoId], [t0].[Id], [t0].[EntityOneId], [t0].[EntityTwoId], [t2].[EntityOneId], [t2].[EntityTwoId], [t2].[Id], [t2].[Name] +SELECT [t].[Id], [t].[CollectionInverseId], [t].[ExtraId], [t].[Name], [t].[ReferenceInverseId], [e].[Id], [t].[EntityOneId], [t].[EntityTwoId], [t0].[Id], [t0].[EntityOneId], [t0].[EntityTwoId], [t0].[Id0], [t2].[EntityOneId], [t2].[EntityTwoId], [t2].[Id], [t2].[Name], [t0].[CollectionInverseId], [t0].[ExtraId], [t0].[Name0], [t0].[ReferenceInverseId] FROM [EntityOnes] AS [e] INNER JOIN ( SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[ExtraId], [e1].[Name], [e1].[ReferenceInverseId], [e0].[EntityOneId], [e0].[EntityTwoId] diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServerTest.cs index 390ba4d56ec..132e0b2f6cc 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServerTest.cs @@ -1351,7 +1351,7 @@ public override async Task Complex_multi_include_with_order_by_and_paging_joins_ @"@__p_0='0' @__p_1='10' -SELECT [t].[Id], [t].[Date], [t].[Name], [t].[OneToMany_Optional_Self_Inverse1Id], [t].[OneToMany_Required_Self_Inverse1Id], [t].[OneToOne_Optional_Self1Id], [l0].[Id], [l0].[Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Optional_Self_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToMany_Required_Self_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[OneToOne_Optional_Self2Id], [l1].[Id], [l1].[Date], [l1].[Level1_Optional_Id], [l1].[Level1_Required_Id], [l1].[Name], [l1].[OneToMany_Optional_Inverse2Id], [l1].[OneToMany_Optional_Self_Inverse2Id], [l1].[OneToMany_Required_Inverse2Id], [l1].[OneToMany_Required_Self_Inverse2Id], [l1].[OneToOne_Optional_PK_Inverse2Id], [l1].[OneToOne_Optional_Self2Id], [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Optional_Self_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToMany_Required_Self_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[OneToOne_Optional_Self3Id], [l3].[Id], [l3].[Level2_Optional_Id], [l3].[Level2_Required_Id], [l3].[Name], [l3].[OneToMany_Optional_Inverse3Id], [l3].[OneToMany_Optional_Self_Inverse3Id], [l3].[OneToMany_Required_Inverse3Id], [l3].[OneToMany_Required_Self_Inverse3Id], [l3].[OneToOne_Optional_PK_Inverse3Id], [l3].[OneToOne_Optional_Self3Id] +SELECT [t].[Id], [t].[Date], [t].[Name], [t].[OneToMany_Optional_Self_Inverse1Id], [t].[OneToMany_Required_Self_Inverse1Id], [t].[OneToOne_Optional_Self1Id], [l0].[Id], [l0].[Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Optional_Self_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToMany_Required_Self_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[OneToOne_Optional_Self2Id], [l1].[Id], [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Optional_Self_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToMany_Required_Self_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[OneToOne_Optional_Self3Id], [l1].[Date], [l1].[Level1_Optional_Id], [l1].[Level1_Required_Id], [l1].[Name], [l1].[OneToMany_Optional_Inverse2Id], [l1].[OneToMany_Optional_Self_Inverse2Id], [l1].[OneToMany_Required_Inverse2Id], [l1].[OneToMany_Required_Self_Inverse2Id], [l1].[OneToOne_Optional_PK_Inverse2Id], [l1].[OneToOne_Optional_Self2Id], [l3].[Id], [l3].[Level2_Optional_Id], [l3].[Level2_Required_Id], [l3].[Name], [l3].[OneToMany_Optional_Inverse3Id], [l3].[OneToMany_Optional_Self_Inverse3Id], [l3].[OneToMany_Required_Inverse3Id], [l3].[OneToMany_Required_Self_Inverse3Id], [l3].[OneToOne_Optional_PK_Inverse3Id], [l3].[OneToOne_Optional_Self3Id] FROM ( SELECT [l].[Id], [l].[Date], [l].[Name], [l].[OneToMany_Optional_Self_Inverse1Id], [l].[OneToMany_Required_Self_Inverse1Id], [l].[OneToOne_Optional_Self1Id] FROM [LevelOne] AS [l] @@ -1391,7 +1391,7 @@ public override async Task Multiple_include_with_multiple_optional_navigations(b await base.Multiple_include_with_multiple_optional_navigations(async); AssertSql( - @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[OneToMany_Optional_Self_Inverse1Id], [l].[OneToMany_Required_Self_Inverse1Id], [l].[OneToOne_Optional_Self1Id], [l0].[Id], [l0].[Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Optional_Self_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToMany_Required_Self_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[OneToOne_Optional_Self2Id], [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Optional_Self_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToMany_Required_Self_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[OneToOne_Optional_Self3Id], [l3].[Id], [l3].[Date], [l3].[Level1_Optional_Id], [l3].[Level1_Required_Id], [l3].[Name], [l3].[OneToMany_Optional_Inverse2Id], [l3].[OneToMany_Optional_Self_Inverse2Id], [l3].[OneToMany_Required_Inverse2Id], [l3].[OneToMany_Required_Self_Inverse2Id], [l3].[OneToOne_Optional_PK_Inverse2Id], [l3].[OneToOne_Optional_Self2Id], [l4].[Id], [l4].[Level2_Optional_Id], [l4].[Level2_Required_Id], [l4].[Name], [l4].[OneToMany_Optional_Inverse3Id], [l4].[OneToMany_Optional_Self_Inverse3Id], [l4].[OneToMany_Required_Inverse3Id], [l4].[OneToMany_Required_Self_Inverse3Id], [l4].[OneToOne_Optional_PK_Inverse3Id], [l4].[OneToOne_Optional_Self3Id], [l1].[Id], [l5].[Id], [l5].[Level2_Optional_Id], [l5].[Level2_Required_Id], [l5].[Name], [l5].[OneToMany_Optional_Inverse3Id], [l5].[OneToMany_Optional_Self_Inverse3Id], [l5].[OneToMany_Required_Inverse3Id], [l5].[OneToMany_Required_Self_Inverse3Id], [l5].[OneToOne_Optional_PK_Inverse3Id], [l5].[OneToOne_Optional_Self3Id] + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[OneToMany_Optional_Self_Inverse1Id], [l].[OneToMany_Required_Self_Inverse1Id], [l].[OneToOne_Optional_Self1Id], [l0].[Id], [l0].[Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Optional_Self_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToMany_Required_Self_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[OneToOne_Optional_Self2Id], [l1].[Id], [l2].[Id], [l3].[Id], [l4].[Id], [l5].[Id], [l5].[Level2_Optional_Id], [l5].[Level2_Required_Id], [l5].[Name], [l5].[OneToMany_Optional_Inverse3Id], [l5].[OneToMany_Optional_Self_Inverse3Id], [l5].[OneToMany_Required_Inverse3Id], [l5].[OneToMany_Required_Self_Inverse3Id], [l5].[OneToOne_Optional_PK_Inverse3Id], [l5].[OneToOne_Optional_Self3Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Optional_Self_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToMany_Required_Self_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[OneToOne_Optional_Self3Id], [l3].[Date], [l3].[Level1_Optional_Id], [l3].[Level1_Required_Id], [l3].[Name], [l3].[OneToMany_Optional_Inverse2Id], [l3].[OneToMany_Optional_Self_Inverse2Id], [l3].[OneToMany_Required_Inverse2Id], [l3].[OneToMany_Required_Self_Inverse2Id], [l3].[OneToOne_Optional_PK_Inverse2Id], [l3].[OneToOne_Optional_Self2Id], [l4].[Level2_Optional_Id], [l4].[Level2_Required_Id], [l4].[Name], [l4].[OneToMany_Optional_Inverse3Id], [l4].[OneToMany_Optional_Self_Inverse3Id], [l4].[OneToMany_Required_Inverse3Id], [l4].[OneToMany_Required_Self_Inverse3Id], [l4].[OneToOne_Optional_PK_Inverse3Id], [l4].[OneToOne_Optional_Self3Id] FROM [LevelOne] AS [l] LEFT JOIN [LevelTwo] AS [l0] ON [l].[Id] = [l0].[Level1_Required_Id] LEFT JOIN [LevelThree] AS [l1] ON [l0].[Id] = [l1].[OneToOne_Optional_PK_Inverse3Id] @@ -2168,7 +2168,7 @@ await base.Complex_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpt async); AssertSql( - @"SELECT [l2].[Id], [l2].[Level3_Optional_Id], [l2].[Level3_Required_Id], [l2].[Name], [l2].[OneToMany_Optional_Inverse4Id], [l2].[OneToMany_Optional_Self_Inverse4Id], [l2].[OneToMany_Required_Inverse4Id], [l2].[OneToMany_Required_Self_Inverse4Id], [l2].[OneToOne_Optional_PK_Inverse4Id], [l2].[OneToOne_Optional_Self4Id], [l14].[Name], [l].[Id], [l0].[Id], [l1].[Id], [t].[Id], [t].[Id0], [t].[Id1], [t].[Id2], [t0].[Id], [t0].[Id0], [t0].[Id1], [t0].[Id2], [l11].[Id], [l12].[Id], [l13].[Id], [l14].[Id], [t1].[Id], [t1].[Date], [t1].[Level1_Optional_Id], [t1].[Level1_Required_Id], [t1].[Name], [t1].[OneToMany_Optional_Inverse2Id], [t1].[OneToMany_Optional_Self_Inverse2Id], [t1].[OneToMany_Required_Inverse2Id], [t1].[OneToMany_Required_Self_Inverse2Id], [t1].[OneToOne_Optional_PK_Inverse2Id], [t1].[OneToOne_Optional_Self2Id] + @"SELECT [l2].[Id], [l2].[Level3_Optional_Id], [l2].[Level3_Required_Id], [l2].[Name], [l2].[OneToMany_Optional_Inverse4Id], [l2].[OneToMany_Optional_Self_Inverse4Id], [l2].[OneToMany_Required_Inverse4Id], [l2].[OneToMany_Required_Self_Inverse4Id], [l2].[OneToOne_Optional_PK_Inverse4Id], [l2].[OneToOne_Optional_Self4Id], [l].[Id], [l0].[Id], [l1].[Id], [t].[Id], [t].[Id0], [t].[Id1], [t].[Id2], [t0].[Id], [t0].[Id0], [t0].[Id1], [t0].[Id2], [l11].[Id], [l12].[Id], [l13].[Id], [l14].[Id], [t1].[Id], [t1].[Date], [t1].[Level1_Optional_Id], [t1].[Level1_Required_Id], [t1].[Name], [t1].[OneToMany_Optional_Inverse2Id], [t1].[OneToMany_Optional_Self_Inverse2Id], [t1].[OneToMany_Required_Inverse2Id], [t1].[OneToMany_Required_Self_Inverse2Id], [t1].[OneToOne_Optional_PK_Inverse2Id], [t1].[OneToOne_Optional_Self2Id], [l14].[Name] FROM [LevelOne] AS [l] LEFT JOIN [LevelTwo] AS [l0] ON [l].[Id] = [l0].[Level1_Required_Id] LEFT JOIN [LevelThree] AS [l1] ON [l0].[Id] = [l1].[Level2_Optional_Id] @@ -4178,32 +4178,34 @@ public override void Member_pushdown_chain_3_levels_deep_entity() base.Member_pushdown_chain_3_levels_deep_entity(); AssertSql( - @"SELECT [t4].[Id], [t4].[Level3_Optional_Id], [t4].[Level3_Required_Id], [t4].[Name], [t4].[OneToMany_Optional_Inverse4Id], [t4].[OneToMany_Optional_Self_Inverse4Id], [t4].[OneToMany_Required_Inverse4Id], [t4].[OneToMany_Required_Self_Inverse4Id], [t4].[OneToOne_Optional_PK_Inverse4Id], [t4].[OneToOne_Optional_Self4Id] + @"SELECT [t4].[Id], [t4].[Level3_Optional_Id], [t4].[Level3_Required_Id], [t4].[Name], [t4].[OneToMany_Optional_Inverse4Id], [t4].[OneToMany_Optional_Self_Inverse4Id], [t4].[OneToMany_Required_Inverse4Id], [t4].[OneToMany_Required_Self_Inverse4Id], [t4].[OneToOne_Optional_PK_Inverse4Id], [t4].[OneToOne_Optional_Self4Id], [t4].[c], [t4].[c0] FROM [LevelOne] AS [l] -LEFT JOIN ( - SELECT [t3].[Id], [t3].[Level3_Optional_Id], [t3].[Level3_Required_Id], [t3].[Name], [t3].[OneToMany_Optional_Inverse4Id], [t3].[OneToMany_Optional_Self_Inverse4Id], [t3].[OneToMany_Required_Inverse4Id], [t3].[OneToMany_Required_Self_Inverse4Id], [t3].[OneToOne_Optional_PK_Inverse4Id], [t3].[OneToOne_Optional_Self4Id], [t3].[Level1_Optional_Id] +OUTER APPLY ( + SELECT [t2].[Id], [t2].[Level3_Optional_Id], [t2].[Level3_Required_Id], [t2].[Name], [t2].[OneToMany_Optional_Inverse4Id], [t2].[OneToMany_Optional_Self_Inverse4Id], [t2].[OneToMany_Required_Inverse4Id], [t2].[OneToMany_Required_Self_Inverse4Id], [t2].[OneToOne_Optional_PK_Inverse4Id], [t2].[OneToOne_Optional_Self4Id], [t2].[c], [t].[c] AS [c0] FROM ( - SELECT [t2].[Id], [t2].[Level3_Optional_Id], [t2].[Level3_Required_Id], [t2].[Name], [t2].[OneToMany_Optional_Inverse4Id], [t2].[OneToMany_Optional_Self_Inverse4Id], [t2].[OneToMany_Required_Inverse4Id], [t2].[OneToMany_Required_Self_Inverse4Id], [t2].[OneToOne_Optional_PK_Inverse4Id], [t2].[OneToOne_Optional_Self4Id], [l0].[Level1_Optional_Id], ROW_NUMBER() OVER(PARTITION BY [l0].[Level1_Optional_Id] ORDER BY [l0].[Id]) AS [row] + SELECT TOP(1) 1 AS [c], [l0].[Id] FROM [LevelTwo] AS [l0] + WHERE [l0].[Level1_Optional_Id] = [l].[Id] + ORDER BY [l0].[Id] + ) AS [t] + OUTER APPLY ( + SELECT [t1].[Id], [t1].[Level3_Optional_Id], [t1].[Level3_Required_Id], [t1].[Name], [t1].[OneToMany_Optional_Inverse4Id], [t1].[OneToMany_Optional_Self_Inverse4Id], [t1].[OneToMany_Required_Inverse4Id], [t1].[OneToMany_Required_Self_Inverse4Id], [t1].[OneToOne_Optional_PK_Inverse4Id], [t1].[OneToOne_Optional_Self4Id], [t0].[c] + FROM ( + SELECT TOP(1) 1 AS [c], [l1].[Id] + FROM [LevelThree] AS [l1] + WHERE [l1].[Level2_Required_Id] = [t].[Id] + ORDER BY [l1].[Id] + ) AS [t0] LEFT JOIN ( - SELECT [t1].[Id], [t1].[Level3_Optional_Id], [t1].[Level3_Required_Id], [t1].[Name], [t1].[OneToMany_Optional_Inverse4Id], [t1].[OneToMany_Optional_Self_Inverse4Id], [t1].[OneToMany_Required_Inverse4Id], [t1].[OneToMany_Required_Self_Inverse4Id], [t1].[OneToOne_Optional_PK_Inverse4Id], [t1].[OneToOne_Optional_Self4Id], [t1].[Level2_Required_Id] + SELECT [t3].[Id], [t3].[Level3_Optional_Id], [t3].[Level3_Required_Id], [t3].[Name], [t3].[OneToMany_Optional_Inverse4Id], [t3].[OneToMany_Optional_Self_Inverse4Id], [t3].[OneToMany_Required_Inverse4Id], [t3].[OneToMany_Required_Self_Inverse4Id], [t3].[OneToOne_Optional_PK_Inverse4Id], [t3].[OneToOne_Optional_Self4Id] FROM ( - SELECT [t0].[Id], [t0].[Level3_Optional_Id], [t0].[Level3_Required_Id], [t0].[Name], [t0].[OneToMany_Optional_Inverse4Id], [t0].[OneToMany_Optional_Self_Inverse4Id], [t0].[OneToMany_Required_Inverse4Id], [t0].[OneToMany_Required_Self_Inverse4Id], [t0].[OneToOne_Optional_PK_Inverse4Id], [t0].[OneToOne_Optional_Self4Id], [l1].[Level2_Required_Id], ROW_NUMBER() OVER(PARTITION BY [l1].[Level2_Required_Id] ORDER BY [l1].[Id]) AS [row] - FROM [LevelThree] AS [l1] - LEFT JOIN ( - SELECT [t].[Id], [t].[Level3_Optional_Id], [t].[Level3_Required_Id], [t].[Name], [t].[OneToMany_Optional_Inverse4Id], [t].[OneToMany_Optional_Self_Inverse4Id], [t].[OneToMany_Required_Inverse4Id], [t].[OneToMany_Required_Self_Inverse4Id], [t].[OneToOne_Optional_PK_Inverse4Id], [t].[OneToOne_Optional_Self4Id] - FROM ( - SELECT [l2].[Id], [l2].[Level3_Optional_Id], [l2].[Level3_Required_Id], [l2].[Name], [l2].[OneToMany_Optional_Inverse4Id], [l2].[OneToMany_Optional_Self_Inverse4Id], [l2].[OneToMany_Required_Inverse4Id], [l2].[OneToMany_Required_Self_Inverse4Id], [l2].[OneToOne_Optional_PK_Inverse4Id], [l2].[OneToOne_Optional_Self4Id], ROW_NUMBER() OVER(PARTITION BY [l2].[Level3_Required_Id] ORDER BY [l2].[Id]) AS [row] - FROM [LevelFour] AS [l2] - ) AS [t] - WHERE [t].[row] <= 1 - ) AS [t0] ON [l1].[Id] = [t0].[Level3_Required_Id] - ) AS [t1] - WHERE [t1].[row] <= 1 - ) AS [t2] ON [l0].[Id] = [t2].[Level2_Required_Id] - ) AS [t3] - WHERE [t3].[row] <= 1 -) AS [t4] ON [l].[Id] = [t4].[Level1_Optional_Id] + SELECT [l2].[Id], [l2].[Level3_Optional_Id], [l2].[Level3_Required_Id], [l2].[Name], [l2].[OneToMany_Optional_Inverse4Id], [l2].[OneToMany_Optional_Self_Inverse4Id], [l2].[OneToMany_Required_Inverse4Id], [l2].[OneToMany_Required_Self_Inverse4Id], [l2].[OneToOne_Optional_PK_Inverse4Id], [l2].[OneToOne_Optional_Self4Id], ROW_NUMBER() OVER(PARTITION BY [l2].[Level3_Required_Id] ORDER BY [l2].[Id]) AS [row] + FROM [LevelFour] AS [l2] + ) AS [t3] + WHERE [t3].[row] <= 1 + ) AS [t1] ON [t0].[Id] = [t1].[Level3_Required_Id] + ) AS [t2] +) AS [t4] ORDER BY [l].[Id]"); } @@ -4343,19 +4345,19 @@ public override async Task Including_reference_navigation_and_projecting_collect await base.Including_reference_navigation_and_projecting_collection_navigation_2(async); AssertSql( - @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[OneToMany_Optional_Self_Inverse1Id], [l].[OneToMany_Required_Self_Inverse1Id], [l].[OneToOne_Optional_Self1Id], [l0].[Id], [l0].[Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Optional_Self_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToMany_Required_Self_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[OneToOne_Optional_Self2Id], [t0].[Id], [t0].[Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Optional_Self_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToMany_Required_Self_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[OneToOne_Optional_Self2Id], [l2].[Id], [l2].[Date], [l2].[Level1_Optional_Id], [l2].[Level1_Required_Id], [l2].[Name], [l2].[OneToMany_Optional_Inverse2Id], [l2].[OneToMany_Optional_Self_Inverse2Id], [l2].[OneToMany_Required_Inverse2Id], [l2].[OneToMany_Required_Self_Inverse2Id], [l2].[OneToOne_Optional_PK_Inverse2Id], [l2].[OneToOne_Optional_Self2Id] + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[OneToMany_Optional_Self_Inverse1Id], [l].[OneToMany_Required_Self_Inverse1Id], [l].[OneToOne_Optional_Self1Id], [l0].[Id], [l0].[Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Optional_Self_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToMany_Required_Self_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[OneToOne_Optional_Self2Id], [l1].[Id], [l1].[Date], [l1].[Level1_Optional_Id], [l1].[Level1_Required_Id], [l1].[Name], [l1].[OneToMany_Optional_Inverse2Id], [l1].[OneToMany_Optional_Self_Inverse2Id], [l1].[OneToMany_Required_Inverse2Id], [l1].[OneToMany_Required_Self_Inverse2Id], [l1].[OneToOne_Optional_PK_Inverse2Id], [l1].[OneToOne_Optional_Self2Id], [t0].[Id], [t0].[Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Optional_Self_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToMany_Required_Self_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[OneToOne_Optional_Self2Id] FROM [LevelOne] AS [l] LEFT JOIN [LevelTwo] AS [l0] ON [l].[Id] = [l0].[Level1_Required_Id] +LEFT JOIN [LevelTwo] AS [l1] ON [l].[Id] = [l1].[OneToMany_Required_Inverse2Id] LEFT JOIN ( SELECT [t].[Id], [t].[Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Optional_Self_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToMany_Required_Self_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[OneToOne_Optional_Self2Id] FROM ( - SELECT [l1].[Id], [l1].[Date], [l1].[Level1_Optional_Id], [l1].[Level1_Required_Id], [l1].[Name], [l1].[OneToMany_Optional_Inverse2Id], [l1].[OneToMany_Optional_Self_Inverse2Id], [l1].[OneToMany_Required_Inverse2Id], [l1].[OneToMany_Required_Self_Inverse2Id], [l1].[OneToOne_Optional_PK_Inverse2Id], [l1].[OneToOne_Optional_Self2Id], ROW_NUMBER() OVER(PARTITION BY [l1].[OneToMany_Required_Inverse2Id] ORDER BY [l1].[Id] DESC) AS [row] - FROM [LevelTwo] AS [l1] + SELECT [l2].[Id], [l2].[Date], [l2].[Level1_Optional_Id], [l2].[Level1_Required_Id], [l2].[Name], [l2].[OneToMany_Optional_Inverse2Id], [l2].[OneToMany_Optional_Self_Inverse2Id], [l2].[OneToMany_Required_Inverse2Id], [l2].[OneToMany_Required_Self_Inverse2Id], [l2].[OneToOne_Optional_PK_Inverse2Id], [l2].[OneToOne_Optional_Self2Id], ROW_NUMBER() OVER(PARTITION BY [l2].[OneToMany_Required_Inverse2Id] ORDER BY [l2].[Id] DESC) AS [row] + FROM [LevelTwo] AS [l2] ) AS [t] WHERE [t].[row] <= 1 ) AS [t0] ON [l].[Id] = [t0].[OneToMany_Required_Inverse2Id] -LEFT JOIN [LevelTwo] AS [l2] ON [l].[Id] = [l2].[OneToMany_Required_Inverse2Id] -ORDER BY [l].[Id], [l0].[Id], [t0].[Id], [l2].[Id]"); +ORDER BY [l].[Id], [l0].[Id], [l1].[Id]"); } public override async Task OrderBy_collection_count_ThenBy_reference_navigation(bool async) @@ -4440,21 +4442,22 @@ public override async Task Select_subquery_single_nested_subquery(bool async) await base.Select_subquery_single_nested_subquery(async); AssertSql( - @"SELECT [t0].[c], [l].[Id], [t0].[Id], [t1].[Id] + @"SELECT [t1].[Id], [t1].[Id0], [t1].[c] FROM [LevelOne] AS [l] -LEFT JOIN ( - SELECT [t].[c], [t].[Id], [t].[OneToMany_Optional_Inverse2Id] +OUTER APPLY ( + SELECT [t].[Id], [t0].[Id] AS [Id0], [t].[c] FROM ( - SELECT 1 AS [c], [l0].[Id], [l0].[OneToMany_Optional_Inverse2Id], ROW_NUMBER() OVER(PARTITION BY [l0].[OneToMany_Optional_Inverse2Id] ORDER BY [l0].[Id]) AS [row] + SELECT TOP(1) 1 AS [c], [l0].[Id] FROM [LevelTwo] AS [l0] + WHERE [l].[Id] = [l0].[OneToMany_Optional_Inverse2Id] + ORDER BY [l0].[Id] ) AS [t] - WHERE [t].[row] <= 1 -) AS [t0] ON [l].[Id] = [t0].[OneToMany_Optional_Inverse2Id] -LEFT JOIN ( - SELECT [l1].[Id], [l1].[OneToMany_Optional_Inverse3Id] - FROM [LevelThree] AS [l1] -) AS [t1] ON [t0].[Id] = [t1].[OneToMany_Optional_Inverse3Id] -ORDER BY [l].[Id], [t0].[Id], [t1].[Id]"); + LEFT JOIN ( + SELECT [l1].[Id], [l1].[OneToMany_Optional_Inverse3Id] + FROM [LevelThree] AS [l1] + ) AS [t0] ON [t].[Id] = [t0].[OneToMany_Optional_Inverse3Id] +) AS [t1] +ORDER BY [l].[Id]"); } public override async Task Select_subquery_single_nested_subquery2(bool async) @@ -4462,25 +4465,26 @@ public override async Task Select_subquery_single_nested_subquery2(bool async) await base.Select_subquery_single_nested_subquery2(async); AssertSql( - @"SELECT [l].[Id], [t2].[c], [t2].[Id], [t2].[Id0], [t2].[Id1] + @"SELECT [l].[Id], [t2].[Id], [t2].[Id0], [t2].[c], [t2].[Id1] FROM [LevelOne] AS [l] LEFT JOIN ( - SELECT [t0].[c], [l0].[Id], [t0].[Id] AS [Id0], [t1].[Id] AS [Id1], [l0].[OneToMany_Optional_Inverse2Id] + SELECT [t1].[Id], [t1].[Id0], [t1].[c], [l0].[Id] AS [Id1], [l0].[OneToMany_Optional_Inverse2Id] FROM [LevelTwo] AS [l0] - LEFT JOIN ( - SELECT [t].[c], [t].[Id], [t].[OneToMany_Optional_Inverse3Id] + OUTER APPLY ( + SELECT [t].[Id], [t0].[Id] AS [Id0], [t].[c] FROM ( - SELECT 1 AS [c], [l1].[Id], [l1].[OneToMany_Optional_Inverse3Id], ROW_NUMBER() OVER(PARTITION BY [l1].[OneToMany_Optional_Inverse3Id] ORDER BY [l1].[Id]) AS [row] + SELECT TOP(1) 1 AS [c], [l1].[Id] FROM [LevelThree] AS [l1] + WHERE [l0].[Id] = [l1].[OneToMany_Optional_Inverse3Id] + ORDER BY [l1].[Id] ) AS [t] - WHERE [t].[row] <= 1 - ) AS [t0] ON [l0].[Id] = [t0].[OneToMany_Optional_Inverse3Id] - LEFT JOIN ( - SELECT [l2].[Id], [l2].[OneToMany_Optional_Inverse4Id] - FROM [LevelFour] AS [l2] - ) AS [t1] ON [t0].[Id] = [t1].[OneToMany_Optional_Inverse4Id] + LEFT JOIN ( + SELECT [l2].[Id], [l2].[OneToMany_Optional_Inverse4Id] + FROM [LevelFour] AS [l2] + ) AS [t0] ON [t].[Id] = [t0].[OneToMany_Optional_Inverse4Id] + ) AS [t1] ) AS [t2] ON [l].[Id] = [t2].[OneToMany_Optional_Inverse2Id] -ORDER BY [l].[Id], [t2].[Id], [t2].[Id0], [t2].[Id1]"); +ORDER BY [l].[Id], [t2].[Id1], [t2].[Id], [t2].[Id0]"); } public override async Task SelectMany_with_outside_reference_to_joined_table_correctly_translated_to_apply(bool async) @@ -4844,10 +4848,10 @@ public override async Task Filtered_include_same_filter_set_on_same_navigation_t await base.Filtered_include_same_filter_set_on_same_navigation_twice_followed_by_ThenIncludes(async); AssertSql( - @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[OneToMany_Optional_Self_Inverse1Id], [l].[OneToMany_Required_Self_Inverse1Id], [l].[OneToOne_Optional_Self1Id], [t0].[Id], [t0].[Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Optional_Self_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToMany_Required_Self_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[OneToOne_Optional_Self2Id], [t0].[Id0], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Name0], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Optional_Self_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToMany_Required_Self_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[OneToOne_Optional_Self3Id], [t0].[Id1], [t0].[Level2_Optional_Id0], [t0].[Level2_Required_Id0], [t0].[Name1], [t0].[OneToMany_Optional_Inverse3Id0], [t0].[OneToMany_Optional_Self_Inverse3Id0], [t0].[OneToMany_Required_Inverse3Id0], [t0].[OneToMany_Required_Self_Inverse3Id0], [t0].[OneToOne_Optional_PK_Inverse3Id0], [t0].[OneToOne_Optional_Self3Id0] + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[OneToMany_Optional_Self_Inverse1Id], [l].[OneToMany_Required_Self_Inverse1Id], [l].[OneToOne_Optional_Self1Id], [t0].[Id], [t0].[Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Optional_Self_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToMany_Required_Self_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[OneToOne_Optional_Self2Id], [t0].[Id0], [t0].[Id1], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Name0], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Optional_Self_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToMany_Required_Self_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[OneToOne_Optional_Self3Id], [t0].[Level2_Optional_Id0], [t0].[Level2_Required_Id0], [t0].[Name1], [t0].[OneToMany_Optional_Inverse3Id0], [t0].[OneToMany_Optional_Self_Inverse3Id0], [t0].[OneToMany_Required_Inverse3Id0], [t0].[OneToMany_Required_Self_Inverse3Id0], [t0].[OneToOne_Optional_PK_Inverse3Id0], [t0].[OneToOne_Optional_Self3Id0] FROM [LevelOne] AS [l] OUTER APPLY ( - SELECT [t].[Id], [t].[Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Optional_Self_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToMany_Required_Self_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[OneToOne_Optional_Self2Id], [l0].[Id] AS [Id0], [l0].[Level2_Optional_Id], [l0].[Level2_Required_Id], [l0].[Name] AS [Name0], [l0].[OneToMany_Optional_Inverse3Id], [l0].[OneToMany_Optional_Self_Inverse3Id], [l0].[OneToMany_Required_Inverse3Id], [l0].[OneToMany_Required_Self_Inverse3Id], [l0].[OneToOne_Optional_PK_Inverse3Id], [l0].[OneToOne_Optional_Self3Id], [l1].[Id] AS [Id1], [l1].[Level2_Optional_Id] AS [Level2_Optional_Id0], [l1].[Level2_Required_Id] AS [Level2_Required_Id0], [l1].[Name] AS [Name1], [l1].[OneToMany_Optional_Inverse3Id] AS [OneToMany_Optional_Inverse3Id0], [l1].[OneToMany_Optional_Self_Inverse3Id] AS [OneToMany_Optional_Self_Inverse3Id0], [l1].[OneToMany_Required_Inverse3Id] AS [OneToMany_Required_Inverse3Id0], [l1].[OneToMany_Required_Self_Inverse3Id] AS [OneToMany_Required_Self_Inverse3Id0], [l1].[OneToOne_Optional_PK_Inverse3Id] AS [OneToOne_Optional_PK_Inverse3Id0], [l1].[OneToOne_Optional_Self3Id] AS [OneToOne_Optional_Self3Id0] + SELECT [t].[Id], [t].[Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Optional_Self_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToMany_Required_Self_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[OneToOne_Optional_Self2Id], [l0].[Id] AS [Id0], [l1].[Id] AS [Id1], [l1].[Level2_Optional_Id], [l1].[Level2_Required_Id], [l1].[Name] AS [Name0], [l1].[OneToMany_Optional_Inverse3Id], [l1].[OneToMany_Optional_Self_Inverse3Id], [l1].[OneToMany_Required_Inverse3Id], [l1].[OneToMany_Required_Self_Inverse3Id], [l1].[OneToOne_Optional_PK_Inverse3Id], [l1].[OneToOne_Optional_Self3Id], [l0].[Level2_Optional_Id] AS [Level2_Optional_Id0], [l0].[Level2_Required_Id] AS [Level2_Required_Id0], [l0].[Name] AS [Name1], [l0].[OneToMany_Optional_Inverse3Id] AS [OneToMany_Optional_Inverse3Id0], [l0].[OneToMany_Optional_Self_Inverse3Id] AS [OneToMany_Optional_Self_Inverse3Id0], [l0].[OneToMany_Required_Inverse3Id] AS [OneToMany_Required_Inverse3Id0], [l0].[OneToMany_Required_Self_Inverse3Id] AS [OneToMany_Required_Self_Inverse3Id0], [l0].[OneToOne_Optional_PK_Inverse3Id] AS [OneToOne_Optional_PK_Inverse3Id0], [l0].[OneToOne_Optional_Self3Id] AS [OneToOne_Optional_Self3Id0] FROM ( SELECT TOP(2) [l2].[Id], [l2].[Date], [l2].[Level1_Optional_Id], [l2].[Level1_Required_Id], [l2].[Name], [l2].[OneToMany_Optional_Inverse2Id], [l2].[OneToMany_Optional_Self_Inverse2Id], [l2].[OneToMany_Required_Inverse2Id], [l2].[OneToMany_Required_Self_Inverse2Id], [l2].[OneToOne_Optional_PK_Inverse2Id], [l2].[OneToOne_Optional_Self2Id] FROM [LevelTwo] AS [l2] @@ -4867,10 +4871,10 @@ await base .Filtered_include_multiple_multi_level_includes_with_first_level_using_filter_include_on_one_of_the_chains_only(async); AssertSql( - @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[OneToMany_Optional_Self_Inverse1Id], [l].[OneToMany_Required_Self_Inverse1Id], [l].[OneToOne_Optional_Self1Id], [t0].[Id], [t0].[Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Optional_Self_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToMany_Required_Self_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[OneToOne_Optional_Self2Id], [t0].[Id0], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Name0], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Optional_Self_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToMany_Required_Self_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[OneToOne_Optional_Self3Id], [t0].[Id1], [t0].[Level2_Optional_Id0], [t0].[Level2_Required_Id0], [t0].[Name1], [t0].[OneToMany_Optional_Inverse3Id0], [t0].[OneToMany_Optional_Self_Inverse3Id0], [t0].[OneToMany_Required_Inverse3Id0], [t0].[OneToMany_Required_Self_Inverse3Id0], [t0].[OneToOne_Optional_PK_Inverse3Id0], [t0].[OneToOne_Optional_Self3Id0] + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[OneToMany_Optional_Self_Inverse1Id], [l].[OneToMany_Required_Self_Inverse1Id], [l].[OneToOne_Optional_Self1Id], [t0].[Id], [t0].[Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Optional_Self_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToMany_Required_Self_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[OneToOne_Optional_Self2Id], [t0].[Id0], [t0].[Id1], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Name0], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Optional_Self_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToMany_Required_Self_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[OneToOne_Optional_Self3Id], [t0].[Level2_Optional_Id0], [t0].[Level2_Required_Id0], [t0].[Name1], [t0].[OneToMany_Optional_Inverse3Id0], [t0].[OneToMany_Optional_Self_Inverse3Id0], [t0].[OneToMany_Required_Inverse3Id0], [t0].[OneToMany_Required_Self_Inverse3Id0], [t0].[OneToOne_Optional_PK_Inverse3Id0], [t0].[OneToOne_Optional_Self3Id0] FROM [LevelOne] AS [l] OUTER APPLY ( - SELECT [t].[Id], [t].[Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Optional_Self_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToMany_Required_Self_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[OneToOne_Optional_Self2Id], [l0].[Id] AS [Id0], [l0].[Level2_Optional_Id], [l0].[Level2_Required_Id], [l0].[Name] AS [Name0], [l0].[OneToMany_Optional_Inverse3Id], [l0].[OneToMany_Optional_Self_Inverse3Id], [l0].[OneToMany_Required_Inverse3Id], [l0].[OneToMany_Required_Self_Inverse3Id], [l0].[OneToOne_Optional_PK_Inverse3Id], [l0].[OneToOne_Optional_Self3Id], [l1].[Id] AS [Id1], [l1].[Level2_Optional_Id] AS [Level2_Optional_Id0], [l1].[Level2_Required_Id] AS [Level2_Required_Id0], [l1].[Name] AS [Name1], [l1].[OneToMany_Optional_Inverse3Id] AS [OneToMany_Optional_Inverse3Id0], [l1].[OneToMany_Optional_Self_Inverse3Id] AS [OneToMany_Optional_Self_Inverse3Id0], [l1].[OneToMany_Required_Inverse3Id] AS [OneToMany_Required_Inverse3Id0], [l1].[OneToMany_Required_Self_Inverse3Id] AS [OneToMany_Required_Self_Inverse3Id0], [l1].[OneToOne_Optional_PK_Inverse3Id] AS [OneToOne_Optional_PK_Inverse3Id0], [l1].[OneToOne_Optional_Self3Id] AS [OneToOne_Optional_Self3Id0] + SELECT [t].[Id], [t].[Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Optional_Self_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToMany_Required_Self_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[OneToOne_Optional_Self2Id], [l0].[Id] AS [Id0], [l1].[Id] AS [Id1], [l1].[Level2_Optional_Id], [l1].[Level2_Required_Id], [l1].[Name] AS [Name0], [l1].[OneToMany_Optional_Inverse3Id], [l1].[OneToMany_Optional_Self_Inverse3Id], [l1].[OneToMany_Required_Inverse3Id], [l1].[OneToMany_Required_Self_Inverse3Id], [l1].[OneToOne_Optional_PK_Inverse3Id], [l1].[OneToOne_Optional_Self3Id], [l0].[Level2_Optional_Id] AS [Level2_Optional_Id0], [l0].[Level2_Required_Id] AS [Level2_Required_Id0], [l0].[Name] AS [Name1], [l0].[OneToMany_Optional_Inverse3Id] AS [OneToMany_Optional_Inverse3Id0], [l0].[OneToMany_Optional_Self_Inverse3Id] AS [OneToMany_Optional_Self_Inverse3Id0], [l0].[OneToMany_Required_Inverse3Id] AS [OneToMany_Required_Inverse3Id0], [l0].[OneToMany_Required_Self_Inverse3Id] AS [OneToMany_Required_Self_Inverse3Id0], [l0].[OneToOne_Optional_PK_Inverse3Id] AS [OneToOne_Optional_PK_Inverse3Id0], [l0].[OneToOne_Optional_Self3Id] AS [OneToOne_Optional_Self3Id0] FROM ( SELECT TOP(2) [l2].[Id], [l2].[Date], [l2].[Level1_Optional_Id], [l2].[Level1_Required_Id], [l2].[Name], [l2].[OneToMany_Optional_Inverse2Id], [l2].[OneToMany_Optional_Self_Inverse2Id], [l2].[OneToMany_Required_Inverse2Id], [l2].[OneToMany_Required_Self_Inverse2Id], [l2].[OneToOne_Optional_PK_Inverse2Id], [l2].[OneToOne_Optional_Self2Id] FROM [LevelTwo] AS [l2] @@ -5471,7 +5475,7 @@ public override async Task Filtered_include_same_filter_set_on_same_navigation_t FROM [LevelOne] AS [l] ORDER BY [l].[Id]", // - @"SELECT [t0].[Id], [t0].[Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Optional_Self_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToMany_Required_Self_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[OneToOne_Optional_Self2Id], [t0].[Id0], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Name0], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Optional_Self_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToMany_Required_Self_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[OneToOne_Optional_Self3Id], [l].[Id] + @"SELECT [t0].[Id], [t0].[Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Optional_Self_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToMany_Required_Self_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[OneToOne_Optional_Self2Id], [l].[Id], [t0].[Id0], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Name0], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Optional_Self_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToMany_Required_Self_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[OneToOne_Optional_Self3Id] FROM [LevelOne] AS [l] CROSS APPLY ( SELECT [t].[Id], [t].[Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Optional_Self_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToMany_Required_Self_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[OneToOne_Optional_Self2Id], [l0].[Id] AS [Id0], [l0].[Level2_Optional_Id], [l0].[Level2_Required_Id], [l0].[Name] AS [Name0], [l0].[OneToMany_Optional_Inverse3Id], [l0].[OneToMany_Optional_Self_Inverse3Id], [l0].[OneToMany_Required_Inverse3Id], [l0].[OneToMany_Required_Self_Inverse3Id], [l0].[OneToOne_Optional_PK_Inverse3Id], [l0].[OneToOne_Optional_Self3Id] @@ -5512,7 +5516,7 @@ await base.Filtered_include_multiple_multi_level_includes_with_first_level_using FROM [LevelOne] AS [l] ORDER BY [l].[Id]", // - @"SELECT [t0].[Id], [t0].[Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Optional_Self_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToMany_Required_Self_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[OneToOne_Optional_Self2Id], [t0].[Id0], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Name0], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Optional_Self_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToMany_Required_Self_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[OneToOne_Optional_Self3Id], [l].[Id] + @"SELECT [t0].[Id], [t0].[Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Optional_Self_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToMany_Required_Self_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[OneToOne_Optional_Self2Id], [l].[Id], [t0].[Id0], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Name0], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Optional_Self_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToMany_Required_Self_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[OneToOne_Optional_Self3Id] FROM [LevelOne] AS [l] CROSS APPLY ( SELECT [t].[Id], [t].[Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Optional_Self_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToMany_Required_Self_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[OneToOne_Optional_Self2Id], [l0].[Id] AS [Id0], [l0].[Level2_Optional_Id], [l0].[Level2_Required_Id], [l0].[Name] AS [Name0], [l0].[OneToMany_Optional_Inverse3Id], [l0].[OneToMany_Optional_Self_Inverse3Id], [l0].[OneToMany_Required_Inverse3Id], [l0].[OneToMany_Required_Self_Inverse3Id], [l0].[OneToOne_Optional_PK_Inverse3Id], [l0].[OneToOne_Optional_Self3Id] @@ -5980,7 +5984,7 @@ public override async Task Let_let_contains_from_outer_let(bool async) await base.Let_let_contains_from_outer_let(async); AssertSql( - @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[OneToMany_Optional_Self_Inverse1Id], [l].[OneToMany_Required_Self_Inverse1Id], [l].[OneToOne_Optional_Self1Id], [t].[Id], [t].[Level2_Optional_Id], [t].[Level2_Required_Id], [t].[Name], [t].[OneToMany_Optional_Inverse3Id], [t].[OneToMany_Optional_Self_Inverse3Id], [t].[OneToMany_Required_Inverse3Id], [t].[OneToMany_Required_Self_Inverse3Id], [t].[OneToOne_Optional_PK_Inverse3Id], [t].[OneToOne_Optional_Self3Id], [l2].[Id], [l2].[Date], [l2].[Level1_Optional_Id], [l2].[Level1_Required_Id], [l2].[Name], [l2].[OneToMany_Optional_Inverse2Id], [l2].[OneToMany_Optional_Self_Inverse2Id], [l2].[OneToMany_Required_Inverse2Id], [l2].[OneToMany_Required_Self_Inverse2Id], [l2].[OneToOne_Optional_PK_Inverse2Id], [l2].[OneToOne_Optional_Self2Id] + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[OneToMany_Optional_Self_Inverse1Id], [l].[OneToMany_Required_Self_Inverse1Id], [l].[OneToOne_Optional_Self1Id], [t].[Id], [l2].[Id], [l2].[Date], [l2].[Level1_Optional_Id], [l2].[Level1_Required_Id], [l2].[Name], [l2].[OneToMany_Optional_Inverse2Id], [l2].[OneToMany_Optional_Self_Inverse2Id], [l2].[OneToMany_Required_Inverse2Id], [l2].[OneToMany_Required_Self_Inverse2Id], [l2].[OneToOne_Optional_PK_Inverse2Id], [l2].[OneToOne_Optional_Self2Id], [t].[Level2_Optional_Id], [t].[Level2_Required_Id], [t].[Name], [t].[OneToMany_Optional_Inverse3Id], [t].[OneToMany_Optional_Self_Inverse3Id], [t].[OneToMany_Required_Inverse3Id], [t].[OneToMany_Required_Self_Inverse3Id], [t].[OneToOne_Optional_PK_Inverse3Id], [t].[OneToOne_Optional_Self3Id] FROM [LevelOne] AS [l] OUTER APPLY ( SELECT [l0].[Id], [l0].[Level2_Optional_Id], [l0].[Level2_Required_Id], [l0].[Name], [l0].[OneToMany_Optional_Inverse3Id], [l0].[OneToMany_Optional_Self_Inverse3Id], [l0].[OneToMany_Required_Inverse3Id], [l0].[OneToMany_Required_Self_Inverse3Id], [l0].[OneToOne_Optional_PK_Inverse3Id], [l0].[OneToOne_Optional_Self3Id] @@ -6129,26 +6133,25 @@ public override async Task Complex_query_with_let_collection_projection_FirstOrD await base.Complex_query_with_let_collection_projection_FirstOrDefault(async); AssertSql( - @"SELECT [t0].[c], [l].[Id], [t0].[Id], [t1].[Name], [t1].[Id] + @"SELECT [t1].[Id], [t1].[Name], [t1].[Id0], [t1].[c] FROM [LevelOne] AS [l] -LEFT JOIN ( - SELECT [t].[c], [t].[Id], [t].[OneToMany_Optional_Inverse2Id] +OUTER APPLY ( + SELECT [t].[Id], [t0].[Name], [t0].[Id] AS [Id0], [t].[c] FROM ( - SELECT 1 AS [c], [l0].[Id], [l0].[OneToMany_Optional_Inverse2Id], ROW_NUMBER() OVER(PARTITION BY [l0].[OneToMany_Optional_Inverse2Id] ORDER BY [l0].[Id]) AS [row] + SELECT TOP(1) 1 AS [c], [l0].[Id] FROM [LevelTwo] AS [l0] - WHERE ([l0].[Name] <> N'Foo') OR [l0].[Name] IS NULL + WHERE ([l].[Id] = [l0].[OneToMany_Optional_Inverse2Id]) AND (([l0].[Name] <> N'Foo') OR [l0].[Name] IS NULL) ) AS [t] - WHERE [t].[row] <= 1 -) AS [t0] ON [l].[Id] = [t0].[OneToMany_Optional_Inverse2Id] -OUTER APPLY ( - SELECT [l1].[Name], [l1].[Id] - FROM [LevelOne] AS [l1] - WHERE EXISTS ( - SELECT 1 - FROM [LevelTwo] AS [l2] - WHERE ([l1].[Id] = [l2].[OneToMany_Optional_Inverse2Id]) AND ([l2].[Id] = [t0].[Id])) + OUTER APPLY ( + SELECT [l1].[Name], [l1].[Id] + FROM [LevelOne] AS [l1] + WHERE EXISTS ( + SELECT 1 + FROM [LevelTwo] AS [l2] + WHERE ([l1].[Id] = [l2].[OneToMany_Optional_Inverse2Id]) AND ([l2].[Id] = [t].[Id])) + ) AS [t0] ) AS [t1] -ORDER BY [l].[Id], [t0].[Id], [t1].[Id]"); +ORDER BY [l].[Id]"); } public override async Task Project_shadow_properties(bool async) @@ -6194,7 +6197,7 @@ public override async Task SelectMany_DefaultIfEmpty_multiple_times_with_joins_p await base.SelectMany_DefaultIfEmpty_multiple_times_with_joins_projecting_a_collection(async); AssertSql( - @"SELECT [l2].[Id], [l2].[Level3_Optional_Id], [l2].[Level3_Required_Id], [l2].[Name], [l2].[OneToMany_Optional_Inverse4Id], [l2].[OneToMany_Optional_Self_Inverse4Id], [l2].[OneToMany_Required_Inverse4Id], [l2].[OneToMany_Required_Self_Inverse4Id], [l2].[OneToOne_Optional_PK_Inverse4Id], [l2].[OneToOne_Optional_Self4Id], [l14].[Name], [l].[Id], [l0].[Id], [l1].[Id], [t].[Id], [t].[Id0], [t].[Id1], [t].[Id2], [t0].[Id], [t0].[Id0], [t0].[Id1], [t0].[Id2], [l11].[Id], [l12].[Id], [l13].[Id], [l14].[Id], [t1].[Id], [t1].[Date], [t1].[Level1_Optional_Id], [t1].[Level1_Required_Id], [t1].[Name], [t1].[OneToMany_Optional_Inverse2Id], [t1].[OneToMany_Optional_Self_Inverse2Id], [t1].[OneToMany_Required_Inverse2Id], [t1].[OneToMany_Required_Self_Inverse2Id], [t1].[OneToOne_Optional_PK_Inverse2Id], [t1].[OneToOne_Optional_Self2Id] + @"SELECT [l2].[Id], [l2].[Level3_Optional_Id], [l2].[Level3_Required_Id], [l2].[Name], [l2].[OneToMany_Optional_Inverse4Id], [l2].[OneToMany_Optional_Self_Inverse4Id], [l2].[OneToMany_Required_Inverse4Id], [l2].[OneToMany_Required_Self_Inverse4Id], [l2].[OneToOne_Optional_PK_Inverse4Id], [l2].[OneToOne_Optional_Self4Id], [l].[Id], [l0].[Id], [l1].[Id], [t].[Id], [t].[Id0], [t].[Id1], [t].[Id2], [t0].[Id], [t0].[Id0], [t0].[Id1], [t0].[Id2], [l11].[Id], [l12].[Id], [l13].[Id], [l14].[Id], [t1].[Id], [t1].[Date], [t1].[Level1_Optional_Id], [t1].[Level1_Required_Id], [t1].[Name], [t1].[OneToMany_Optional_Inverse2Id], [t1].[OneToMany_Optional_Self_Inverse2Id], [t1].[OneToMany_Required_Inverse2Id], [t1].[OneToMany_Required_Self_Inverse2Id], [t1].[OneToOne_Optional_PK_Inverse2Id], [t1].[OneToOne_Optional_Self2Id], [l14].[Name] FROM [LevelOne] AS [l] LEFT JOIN [LevelTwo] AS [l0] ON [l].[Id] = [l0].[Level1_Required_Id] LEFT JOIN [LevelThree] AS [l1] ON [l0].[Id] = [l1].[Level2_Optional_Id] diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs index 06f0730c795..92db0183438 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs @@ -1910,7 +1910,7 @@ public override void Include_on_GroupJoin_SelectMany_DefaultIfEmpty_with_coalesc // Issue#16897 AssertSql( - @"SELECT [g0].[Nickname], [g0].[SquadId], [g0].[AssignedCityName], [g0].[CityOfBirthName], [g0].[Discriminator], [g0].[FullName], [g0].[HasSoulPatch], [g0].[LeaderNickname], [g0].[LeaderSquadId], [g0].[Rank], [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] + @"SELECT [g0].[Nickname], [g0].[SquadId], [g0].[AssignedCityName], [g0].[CityOfBirthName], [g0].[Discriminator], [g0].[FullName], [g0].[HasSoulPatch], [g0].[LeaderNickname], [g0].[LeaderSquadId], [g0].[Rank], [g].[Nickname], [g].[SquadId], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] FROM [Gears] AS [g] LEFT JOIN [Gears] AS [g0] ON [g].[LeaderNickname] = [g0].[Nickname] LEFT JOIN [Weapons] AS [w] ON [g0].[FullName] = [w].[OwnerFullName] @@ -1923,7 +1923,7 @@ public override async Task Include_on_GroupJoin_SelectMany_DefaultIfEmpty_with_c // Issue#16897 AssertSql( - @"SELECT [g0].[Nickname], [g0].[SquadId], [g0].[AssignedCityName], [g0].[CityOfBirthName], [g0].[Discriminator], [g0].[FullName], [g0].[HasSoulPatch], [g0].[LeaderNickname], [g0].[LeaderSquadId], [g0].[Rank], [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId], [w0].[Id], [w0].[AmmunitionType], [w0].[IsAutomatic], [w0].[Name], [w0].[OwnerFullName], [w0].[SynergyWithId] + @"SELECT [g0].[Nickname], [g0].[SquadId], [g0].[AssignedCityName], [g0].[CityOfBirthName], [g0].[Discriminator], [g0].[FullName], [g0].[HasSoulPatch], [g0].[LeaderNickname], [g0].[LeaderSquadId], [g0].[Rank], [g].[Nickname], [g].[SquadId], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [w0].[Id], [w0].[AmmunitionType], [w0].[IsAutomatic], [w0].[Name], [w0].[OwnerFullName], [w0].[SynergyWithId] FROM [Gears] AS [g] LEFT JOIN [Gears] AS [g0] ON [g].[LeaderNickname] = [g0].[Nickname] LEFT JOIN [Weapons] AS [w] ON [g0].[FullName] = [w].[OwnerFullName] @@ -1982,7 +1982,7 @@ public override async Task Include_on_GroupJoin_SelectMany_DefaultIfEmpty_with_i // Issue#16897 AssertSql( - @"SELECT [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOfBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank], [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId], [w0].[Id], [w0].[AmmunitionType], [w0].[IsAutomatic], [w0].[Name], [w0].[OwnerFullName], [w0].[SynergyWithId] + @"SELECT [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOfBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank], [g].[Nickname], [g].[SquadId], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [w0].[Id], [w0].[AmmunitionType], [w0].[IsAutomatic], [w0].[Name], [w0].[OwnerFullName], [w0].[SynergyWithId] FROM [Gears] AS [g] LEFT JOIN ( SELECT [g0].[Nickname], [g0].[SquadId], [g0].[AssignedCityName], [g0].[CityOfBirthName], [g0].[Discriminator], [g0].[FullName], [g0].[HasSoulPatch], [g0].[LeaderNickname], [g0].[LeaderSquadId], [g0].[Rank] @@ -4318,12 +4318,12 @@ public override async Task Correlated_collections_from_left_join_with_additional await base.Correlated_collections_from_left_join_with_additional_elements_projected_of_that_join(async); AssertSql( - @"SELECT [w].[Id], [g].[Nickname], [g].[SquadId], [s].[Id], [t0].[Rank], [t0].[Nickname], [t0].[SquadId], [t0].[Id], [t0].[AmmunitionType], [t0].[IsAutomatic], [t0].[Name], [t0].[OwnerFullName], [t0].[SynergyWithId] + @"SELECT [w].[Id], [g].[Nickname], [g].[SquadId], [s].[Id], [t0].[Nickname], [t0].[SquadId], [t0].[Id], [t0].[AmmunitionType], [t0].[IsAutomatic], [t0].[Name], [t0].[OwnerFullName], [t0].[SynergyWithId], [t0].[Rank] FROM [Weapons] AS [w] LEFT JOIN [Gears] AS [g] ON [w].[OwnerFullName] = [g].[FullName] LEFT JOIN [Squads] AS [s] ON [g].[SquadId] = [s].[Id] LEFT JOIN ( - SELECT [g0].[Rank], [g0].[Nickname], [g0].[SquadId], [t].[Id], [t].[AmmunitionType], [t].[IsAutomatic], [t].[Name], [t].[OwnerFullName], [t].[SynergyWithId], [g0].[FullName] + SELECT [g0].[Nickname], [g0].[SquadId], [t].[Id], [t].[AmmunitionType], [t].[IsAutomatic], [t].[Name], [t].[OwnerFullName], [t].[SynergyWithId], [g0].[Rank], [g0].[FullName] FROM [Gears] AS [g0] LEFT JOIN ( SELECT [w0].[Id], [w0].[AmmunitionType], [w0].[IsAutomatic], [w0].[Name], [w0].[OwnerFullName], [w0].[SynergyWithId] @@ -7361,7 +7361,7 @@ public override async Task Correlated_collection_take(bool async) await base.Correlated_collection_take(async); AssertSql( - @"SELECT [g].[Nickname], [c].[Name], [c].[Location], [c].[Nation], [g].[SquadId], [t0].[Id], [t0].[AmmunitionType], [t0].[IsAutomatic], [t0].[Name], [t0].[OwnerFullName], [t0].[SynergyWithId] + @"SELECT [g].[Nickname], [g].[SquadId], [c].[Name], [t0].[Id], [t0].[AmmunitionType], [t0].[IsAutomatic], [t0].[Name], [t0].[OwnerFullName], [t0].[SynergyWithId], [c].[Location], [c].[Nation] FROM [Gears] AS [g] INNER JOIN [Cities] AS [c] ON [g].[CityOfBirthName] = [c].[Name] LEFT JOIN ( diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/InheritanceRelationshipsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/InheritanceRelationshipsQuerySqlServerTest.cs index 713b7ac7282..b942096b8c1 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/InheritanceRelationshipsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/InheritanceRelationshipsQuerySqlServerTest.cs @@ -24,7 +24,7 @@ public override async Task Include_reference_with_inheritance(bool async) await base.Include_reference_with_inheritance(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[Id], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name] FROM [BaseEntities] AS [b] LEFT JOIN [BaseReferencesOnBase] AS [b0] ON [b].[Id] = [b0].[BaseParentId] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b].[Id] = [b1].[BaseInheritanceRelationshipEntityId] @@ -37,7 +37,7 @@ public override async Task Include_reference_with_inheritance_reverse(bool async await base.Include_reference_with_inheritance_reverse(async); AssertSql( - @"SELECT [b].[Id], [b].[BaseParentId], [b].[Discriminator], [b].[Name], [b0].[Id], [b0].[Discriminator], [b0].[Name], [b0].[BaseId], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [b0].[OwnedReferenceOnDerived_Id], [b0].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name] + @"SELECT [b].[Id], [b].[BaseParentId], [b].[Discriminator], [b].[Name], [b0].[Id], [b0].[Discriminator], [b0].[Name], [b0].[BaseId], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [b0].[OwnedReferenceOnDerived_Id], [b0].[OwnedReferenceOnDerived_Name] FROM [BaseReferencesOnBase] AS [b] LEFT JOIN [BaseEntities] AS [b0] ON [b].[BaseParentId] = [b0].[Id] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b0].[Id] = [b1].[BaseInheritanceRelationshipEntityId] @@ -50,7 +50,7 @@ public override async Task Include_self_reference_with_inheritance(bool async) await base.Include_self_reference_with_inheritance(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[Discriminator], [t].[Name], [t].[BaseId], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [b3].[BaseInheritanceRelationshipEntityId], [b3].[Id], [b3].[Name], [b4].[DerivedInheritanceRelationshipEntityId], [b4].[Id], [b4].[Name] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [t].[Discriminator], [t].[Name], [t].[BaseId], [b3].[BaseInheritanceRelationshipEntityId], [b3].[Id], [b3].[Name], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [b4].[DerivedInheritanceRelationshipEntityId], [b4].[Id], [b4].[Name], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name] FROM [BaseEntities] AS [b] LEFT JOIN ( SELECT [b0].[Id], [b0].[Discriminator], [b0].[Name], [b0].[BaseId], [b0].[Id] AS [Id0], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [b0].[OwnedReferenceOnDerived_Id], [b0].[OwnedReferenceOnDerived_Name] @@ -69,7 +69,7 @@ public override async Task Include_self_reference_with_inheritance_reverse(bool await base.Include_self_reference_with_inheritance_reverse(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[Id], [b0].[Discriminator], [b0].[Name], [b0].[BaseId], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [b0].[OwnedReferenceOnDerived_Id], [b0].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [b3].[BaseInheritanceRelationshipEntityId], [b3].[Id], [b3].[Name], [b4].[DerivedInheritanceRelationshipEntityId], [b4].[Id], [b4].[Name] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[Discriminator], [b0].[Name], [b0].[BaseId], [b3].[BaseInheritanceRelationshipEntityId], [b3].[Id], [b3].[Name], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [b4].[DerivedInheritanceRelationshipEntityId], [b4].[Id], [b4].[Name], [b0].[OwnedReferenceOnDerived_Id], [b0].[OwnedReferenceOnDerived_Name] FROM [BaseEntities] AS [b] LEFT JOIN [BaseEntities] AS [b0] ON [b].[BaseId] = [b0].[Id] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b].[Id] = [b1].[BaseInheritanceRelationshipEntityId] @@ -85,7 +85,7 @@ public override async Task Include_reference_with_inheritance_with_filter(bool a await base.Include_reference_with_inheritance_with_filter(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[Id], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name] FROM [BaseEntities] AS [b] LEFT JOIN [BaseReferencesOnBase] AS [b0] ON [b].[Id] = [b0].[BaseParentId] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b].[Id] = [b1].[BaseInheritanceRelationshipEntityId] @@ -99,7 +99,7 @@ public override async Task Include_reference_with_inheritance_with_filter_revers await base.Include_reference_with_inheritance_with_filter_reverse(async); AssertSql( - @"SELECT [b].[Id], [b].[BaseParentId], [b].[Discriminator], [b].[Name], [b0].[Id], [b0].[Discriminator], [b0].[Name], [b0].[BaseId], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [b0].[OwnedReferenceOnDerived_Id], [b0].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name] + @"SELECT [b].[Id], [b].[BaseParentId], [b].[Discriminator], [b].[Name], [b0].[Id], [b0].[Discriminator], [b0].[Name], [b0].[BaseId], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [b0].[OwnedReferenceOnDerived_Id], [b0].[OwnedReferenceOnDerived_Name] FROM [BaseReferencesOnBase] AS [b] LEFT JOIN [BaseEntities] AS [b0] ON [b].[BaseParentId] = [b0].[Id] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b0].[Id] = [b1].[BaseInheritanceRelationshipEntityId] @@ -113,7 +113,7 @@ public override async Task Include_reference_without_inheritance(bool async) await base.Include_reference_without_inheritance(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [r].[Id], [r].[Name], [r].[ParentId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [r].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [r].[Name], [r].[ParentId] FROM [BaseEntities] AS [b] LEFT JOIN [ReferencesOnBase] AS [r] ON [b].[Id] = [r].[ParentId] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] @@ -126,7 +126,7 @@ public override async Task Include_reference_without_inheritance_reverse(bool as await base.Include_reference_without_inheritance_reverse(async); AssertSql( - @"SELECT [r].[Id], [r].[Name], [r].[ParentId], [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name] + @"SELECT [r].[Id], [r].[Name], [r].[ParentId], [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name] FROM [ReferencesOnBase] AS [r] LEFT JOIN [BaseEntities] AS [b] ON [r].[ParentId] = [b].[Id] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] @@ -139,7 +139,7 @@ public override async Task Include_reference_without_inheritance_with_filter(boo await base.Include_reference_without_inheritance_with_filter(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [r].[Id], [r].[Name], [r].[ParentId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [r].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [r].[Name], [r].[ParentId] FROM [BaseEntities] AS [b] LEFT JOIN [ReferencesOnBase] AS [r] ON [b].[Id] = [r].[ParentId] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] @@ -153,7 +153,7 @@ public override async Task Include_reference_without_inheritance_with_filter_rev await base.Include_reference_without_inheritance_with_filter_reverse(async); AssertSql( - @"SELECT [r].[Id], [r].[Name], [r].[ParentId], [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name] + @"SELECT [r].[Id], [r].[Name], [r].[ParentId], [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name] FROM [ReferencesOnBase] AS [r] LEFT JOIN [BaseEntities] AS [b] ON [r].[ParentId] = [b].[Id] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] @@ -167,7 +167,7 @@ public override async Task Include_collection_with_inheritance(bool async) await base.Include_collection_with_inheritance(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[Id], [b2].[BaseParentId], [b2].[Discriminator], [b2].[Name], [b2].[DerivedProperty] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b2].[Id], [b2].[BaseParentId], [b2].[Discriminator], [b2].[Name], [b2].[DerivedProperty] FROM [BaseEntities] AS [b] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] LEFT JOIN [BaseEntities_OwnedCollectionOnDerived] AS [b1] ON [b].[Id] = [b1].[DerivedInheritanceRelationshipEntityId] @@ -180,7 +180,7 @@ public override async Task Include_collection_with_inheritance_reverse(bool asyn await base.Include_collection_with_inheritance_reverse(async); AssertSql( - @"SELECT [b].[Id], [b].[BaseParentId], [b].[Discriminator], [b].[Name], [b].[DerivedProperty], [b0].[Id], [b0].[Discriminator], [b0].[Name], [b0].[BaseId], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [b0].[OwnedReferenceOnDerived_Id], [b0].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name] + @"SELECT [b].[Id], [b].[BaseParentId], [b].[Discriminator], [b].[Name], [b].[DerivedProperty], [b0].[Id], [b0].[Discriminator], [b0].[Name], [b0].[BaseId], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [b0].[OwnedReferenceOnDerived_Id], [b0].[OwnedReferenceOnDerived_Name] FROM [BaseCollectionsOnBase] AS [b] LEFT JOIN [BaseEntities] AS [b0] ON [b].[BaseParentId] = [b0].[Id] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b0].[Id] = [b1].[BaseInheritanceRelationshipEntityId] @@ -193,7 +193,7 @@ public override async Task Include_collection_with_inheritance_with_filter(bool await base.Include_collection_with_inheritance_with_filter(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[Id], [b2].[BaseParentId], [b2].[Discriminator], [b2].[Name], [b2].[DerivedProperty] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b2].[Id], [b2].[BaseParentId], [b2].[Discriminator], [b2].[Name], [b2].[DerivedProperty] FROM [BaseEntities] AS [b] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] LEFT JOIN [BaseEntities_OwnedCollectionOnDerived] AS [b1] ON [b].[Id] = [b1].[DerivedInheritanceRelationshipEntityId] @@ -207,7 +207,7 @@ public override async Task Include_collection_with_inheritance_with_filter_rever await base.Include_collection_with_inheritance_with_filter_reverse(async); AssertSql( - @"SELECT [b].[Id], [b].[BaseParentId], [b].[Discriminator], [b].[Name], [b].[DerivedProperty], [b0].[Id], [b0].[Discriminator], [b0].[Name], [b0].[BaseId], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [b0].[OwnedReferenceOnDerived_Id], [b0].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name] + @"SELECT [b].[Id], [b].[BaseParentId], [b].[Discriminator], [b].[Name], [b].[DerivedProperty], [b0].[Id], [b0].[Discriminator], [b0].[Name], [b0].[BaseId], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [b0].[OwnedReferenceOnDerived_Id], [b0].[OwnedReferenceOnDerived_Name] FROM [BaseCollectionsOnBase] AS [b] LEFT JOIN [BaseEntities] AS [b0] ON [b].[BaseParentId] = [b0].[Id] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b0].[Id] = [b1].[BaseInheritanceRelationshipEntityId] @@ -221,7 +221,7 @@ public override async Task Include_collection_without_inheritance(bool async) await base.Include_collection_without_inheritance(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [c].[Id], [c].[Name], [c].[ParentId] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [c].[Id], [c].[Name], [c].[ParentId] FROM [BaseEntities] AS [b] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] LEFT JOIN [BaseEntities_OwnedCollectionOnDerived] AS [b1] ON [b].[Id] = [b1].[DerivedInheritanceRelationshipEntityId] @@ -234,7 +234,7 @@ public override async Task Include_collection_without_inheritance_reverse(bool a await base.Include_collection_without_inheritance_reverse(async); AssertSql( - @"SELECT [c].[Id], [c].[Name], [c].[ParentId], [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name] + @"SELECT [c].[Id], [c].[Name], [c].[ParentId], [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name] FROM [CollectionsOnBase] AS [c] LEFT JOIN [BaseEntities] AS [b] ON [c].[ParentId] = [b].[Id] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] @@ -247,7 +247,7 @@ public override async Task Include_collection_without_inheritance_with_filter(bo await base.Include_collection_without_inheritance_with_filter(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [c].[Id], [c].[Name], [c].[ParentId] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [c].[Id], [c].[Name], [c].[ParentId] FROM [BaseEntities] AS [b] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] LEFT JOIN [BaseEntities_OwnedCollectionOnDerived] AS [b1] ON [b].[Id] = [b1].[DerivedInheritanceRelationshipEntityId] @@ -261,7 +261,7 @@ public override async Task Include_collection_without_inheritance_with_filter_re await base.Include_collection_without_inheritance_with_filter_reverse(async); AssertSql( - @"SELECT [c].[Id], [c].[Name], [c].[ParentId], [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name] + @"SELECT [c].[Id], [c].[Name], [c].[ParentId], [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name] FROM [CollectionsOnBase] AS [c] LEFT JOIN [BaseEntities] AS [b] ON [c].[ParentId] = [b].[Id] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] @@ -275,7 +275,7 @@ public override async Task Include_reference_with_inheritance_on_derived1(bool a await base.Include_reference_with_inheritance_on_derived1(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[Id], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name] FROM [BaseEntities] AS [b] LEFT JOIN [BaseReferencesOnBase] AS [b0] ON [b].[Id] = [b0].[BaseParentId] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b].[Id] = [b1].[BaseInheritanceRelationshipEntityId] @@ -289,7 +289,7 @@ public override async Task Include_reference_with_inheritance_on_derived2(bool a await base.Include_reference_with_inheritance_on_derived2(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[Id], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name], [b0].[DerivedInheritanceRelationshipEntityId], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name], [b0].[DerivedInheritanceRelationshipEntityId] FROM [BaseEntities] AS [b] LEFT JOIN [BaseReferencesOnDerived] AS [b0] ON [b].[Id] = [b0].[BaseParentId] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b].[Id] = [b1].[BaseInheritanceRelationshipEntityId] @@ -303,7 +303,7 @@ public override async Task Include_reference_with_inheritance_on_derived4(bool a await base.Include_reference_with_inheritance_on_derived4(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Discriminator], [t].[Name], [t].[DerivedInheritanceRelationshipEntityId], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [t].[BaseParentId], [t].[Discriminator], [t].[Name], [t].[DerivedInheritanceRelationshipEntityId] FROM [BaseEntities] AS [b] LEFT JOIN ( SELECT [b0].[Id], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name], [b0].[DerivedInheritanceRelationshipEntityId] @@ -321,7 +321,7 @@ public override async Task Include_reference_with_inheritance_on_derived_reverse await base.Include_reference_with_inheritance_on_derived_reverse(async); AssertSql( - @"SELECT [b].[Id], [b].[BaseParentId], [b].[Discriminator], [b].[Name], [b].[DerivedInheritanceRelationshipEntityId], [t].[Id], [t].[Discriminator], [t].[Name], [t].[BaseId], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name] + @"SELECT [b].[Id], [b].[BaseParentId], [b].[Discriminator], [b].[Name], [b].[DerivedInheritanceRelationshipEntityId], [t].[Id], [t].[Discriminator], [t].[Name], [t].[BaseId], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name] FROM [BaseReferencesOnDerived] AS [b] LEFT JOIN ( SELECT [b0].[Id], [b0].[Discriminator], [b0].[Name], [b0].[BaseId], [b0].[Id] AS [Id0], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [b0].[OwnedReferenceOnDerived_Id], [b0].[OwnedReferenceOnDerived_Name] @@ -338,7 +338,7 @@ public override async Task Include_reference_with_inheritance_on_derived_with_fi await base.Include_reference_with_inheritance_on_derived_with_filter1(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[Id], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name] FROM [BaseEntities] AS [b] LEFT JOIN [BaseReferencesOnBase] AS [b0] ON [b].[Id] = [b0].[BaseParentId] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b].[Id] = [b1].[BaseInheritanceRelationshipEntityId] @@ -352,7 +352,7 @@ public override async Task Include_reference_with_inheritance_on_derived_with_fi await base.Include_reference_with_inheritance_on_derived_with_filter2(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[Id], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name], [b0].[DerivedInheritanceRelationshipEntityId], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name], [b0].[DerivedInheritanceRelationshipEntityId] FROM [BaseEntities] AS [b] LEFT JOIN [BaseReferencesOnDerived] AS [b0] ON [b].[Id] = [b0].[BaseParentId] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b].[Id] = [b1].[BaseInheritanceRelationshipEntityId] @@ -366,7 +366,7 @@ public override async Task Include_reference_with_inheritance_on_derived_with_fi await base.Include_reference_with_inheritance_on_derived_with_filter4(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Discriminator], [t].[Name], [t].[DerivedInheritanceRelationshipEntityId], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [t].[BaseParentId], [t].[Discriminator], [t].[Name], [t].[DerivedInheritanceRelationshipEntityId] FROM [BaseEntities] AS [b] LEFT JOIN ( SELECT [b0].[Id], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name], [b0].[DerivedInheritanceRelationshipEntityId] @@ -384,7 +384,7 @@ public override async Task Include_reference_with_inheritance_on_derived_with_fi await base.Include_reference_with_inheritance_on_derived_with_filter_reverse(async); AssertSql( - @"SELECT [b].[Id], [b].[BaseParentId], [b].[Discriminator], [b].[Name], [b].[DerivedInheritanceRelationshipEntityId], [t].[Id], [t].[Discriminator], [t].[Name], [t].[BaseId], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name] + @"SELECT [b].[Id], [b].[BaseParentId], [b].[Discriminator], [b].[Name], [b].[DerivedInheritanceRelationshipEntityId], [t].[Id], [t].[Discriminator], [t].[Name], [t].[BaseId], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name] FROM [BaseReferencesOnDerived] AS [b] LEFT JOIN ( SELECT [b0].[Id], [b0].[Discriminator], [b0].[Name], [b0].[BaseId], [b0].[Id] AS [Id0], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [b0].[OwnedReferenceOnDerived_Id], [b0].[OwnedReferenceOnDerived_Name] @@ -402,7 +402,7 @@ public override async Task Include_reference_without_inheritance_on_derived1(boo await base.Include_reference_without_inheritance_on_derived1(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [r].[Id], [r].[Name], [r].[ParentId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [r].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [r].[Name], [r].[ParentId] FROM [BaseEntities] AS [b] LEFT JOIN [ReferencesOnBase] AS [r] ON [b].[Id] = [r].[ParentId] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] @@ -416,7 +416,7 @@ public override async Task Include_reference_without_inheritance_on_derived2(boo await base.Include_reference_without_inheritance_on_derived2(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [r].[Id], [r].[Name], [r].[ParentId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [r].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [r].[Name], [r].[ParentId] FROM [BaseEntities] AS [b] LEFT JOIN [ReferencesOnDerived] AS [r] ON [b].[Id] = [r].[ParentId] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] @@ -430,7 +430,7 @@ public override async Task Include_reference_without_inheritance_on_derived_reve await base.Include_reference_without_inheritance_on_derived_reverse(async); AssertSql( - @"SELECT [r].[Id], [r].[Name], [r].[ParentId], [t].[Id], [t].[Discriminator], [t].[Name], [t].[BaseId], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name] + @"SELECT [r].[Id], [r].[Name], [r].[ParentId], [t].[Id], [t].[Discriminator], [t].[Name], [t].[BaseId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name] FROM [ReferencesOnDerived] AS [r] LEFT JOIN ( SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[Id] AS [Id0], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name] @@ -447,7 +447,7 @@ public override async Task Include_collection_with_inheritance_on_derived1(bool await base.Include_collection_with_inheritance_on_derived1(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[Id], [b2].[BaseParentId], [b2].[Discriminator], [b2].[Name], [b2].[DerivedProperty] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b2].[Id], [b2].[BaseParentId], [b2].[Discriminator], [b2].[Name], [b2].[DerivedProperty] FROM [BaseEntities] AS [b] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] LEFT JOIN [BaseEntities_OwnedCollectionOnDerived] AS [b1] ON [b].[Id] = [b1].[DerivedInheritanceRelationshipEntityId] @@ -461,7 +461,7 @@ public override async Task Include_collection_with_inheritance_on_derived2(bool await base.Include_collection_with_inheritance_on_derived2(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[Id], [b2].[Discriminator], [b2].[Name], [b2].[ParentId], [b2].[DerivedInheritanceRelationshipEntityId] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b2].[Id], [b2].[Discriminator], [b2].[Name], [b2].[ParentId], [b2].[DerivedInheritanceRelationshipEntityId] FROM [BaseEntities] AS [b] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] LEFT JOIN [BaseEntities_OwnedCollectionOnDerived] AS [b1] ON [b].[Id] = [b1].[DerivedInheritanceRelationshipEntityId] @@ -475,7 +475,7 @@ public override async Task Include_collection_with_inheritance_on_derived3(bool await base.Include_collection_with_inheritance_on_derived3(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [t].[Id], [t].[Discriminator], [t].[Name], [t].[ParentId], [t].[DerivedInheritanceRelationshipEntityId] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[Discriminator], [t].[Name], [t].[ParentId], [t].[DerivedInheritanceRelationshipEntityId] FROM [BaseEntities] AS [b] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] LEFT JOIN [BaseEntities_OwnedCollectionOnDerived] AS [b1] ON [b].[Id] = [b1].[DerivedInheritanceRelationshipEntityId] @@ -493,7 +493,7 @@ public override async Task Include_collection_with_inheritance_on_derived_revers await base.Include_collection_with_inheritance_on_derived_reverse(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[ParentId], [b].[DerivedInheritanceRelationshipEntityId], [t].[Id], [t].[Discriminator], [t].[Name], [t].[BaseId], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[ParentId], [b].[DerivedInheritanceRelationshipEntityId], [t].[Id], [t].[Discriminator], [t].[Name], [t].[BaseId], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name] FROM [BaseCollectionsOnDerived] AS [b] LEFT JOIN ( SELECT [b0].[Id], [b0].[Discriminator], [b0].[Name], [b0].[BaseId], [b0].[Id] AS [Id0], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [b0].[OwnedReferenceOnDerived_Id], [b0].[OwnedReferenceOnDerived_Name] @@ -510,7 +510,7 @@ public override async Task Nested_include_with_inheritance_reference_reference(b await base.Nested_include_with_inheritance_reference_reference(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[Id], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name], [n].[Id], [n].[Discriminator], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[Id], [n].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name], [n].[Discriminator], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId] FROM [BaseEntities] AS [b] LEFT JOIN [BaseReferencesOnBase] AS [b0] ON [b].[Id] = [b0].[BaseParentId] LEFT JOIN [NestedReferences] AS [n] ON [b0].[Id] = [n].[ParentReferenceId] @@ -524,7 +524,7 @@ public override async Task Nested_include_with_inheritance_reference_reference_o await base.Nested_include_with_inheritance_reference_reference_on_base(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[Id], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name], [n].[Id], [n].[Discriminator], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[Id], [n].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name], [n].[Discriminator], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId] FROM [BaseEntities] AS [b] LEFT JOIN [BaseReferencesOnBase] AS [b0] ON [b].[Id] = [b0].[BaseParentId] LEFT JOIN [NestedReferences] AS [n] ON [b0].[Id] = [n].[ParentReferenceId] @@ -539,7 +539,7 @@ public override async Task Nested_include_with_inheritance_reference_reference_r await base.Nested_include_with_inheritance_reference_reference_reverse(async); AssertSql( - @"SELECT [n].[Id], [n].[Discriminator], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId], [b].[Id], [b].[BaseParentId], [b].[Discriminator], [b].[Name], [b0].[Id], [b0].[Discriminator], [b0].[Name], [b0].[BaseId], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [b0].[OwnedReferenceOnDerived_Id], [b0].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name] + @"SELECT [n].[Id], [n].[Discriminator], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId], [b].[Id], [b].[BaseParentId], [b].[Discriminator], [b].[Name], [b0].[Id], [b0].[Discriminator], [b0].[Name], [b0].[BaseId], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [b0].[OwnedReferenceOnDerived_Id], [b0].[OwnedReferenceOnDerived_Name] FROM [NestedReferences] AS [n] LEFT JOIN [BaseReferencesOnBase] AS [b] ON [n].[ParentReferenceId] = [b].[Id] LEFT JOIN [BaseEntities] AS [b0] ON [b].[BaseParentId] = [b0].[Id] @@ -553,7 +553,7 @@ public override async Task Nested_include_with_inheritance_reference_collection( await base.Nested_include_with_inheritance_reference_collection(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[Id], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [n].[Id], [n].[Discriminator], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name], [n].[Id], [n].[Discriminator], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId] FROM [BaseEntities] AS [b] LEFT JOIN [BaseReferencesOnBase] AS [b0] ON [b].[Id] = [b0].[BaseParentId] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b].[Id] = [b1].[BaseInheritanceRelationshipEntityId] @@ -567,7 +567,7 @@ public override async Task Nested_include_with_inheritance_reference_collection_ await base.Nested_include_with_inheritance_reference_collection_on_base(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[Id], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [n].[Id], [n].[Discriminator], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name], [n].[Id], [n].[Discriminator], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId] FROM [BaseEntities] AS [b] LEFT JOIN [BaseReferencesOnBase] AS [b0] ON [b].[Id] = [b0].[BaseParentId] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b].[Id] = [b1].[BaseInheritanceRelationshipEntityId] @@ -582,7 +582,7 @@ public override async Task Nested_include_with_inheritance_reference_collection_ await base.Nested_include_with_inheritance_reference_collection_reverse(async); AssertSql( - @"SELECT [n].[Id], [n].[Discriminator], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId], [b].[Id], [b].[BaseParentId], [b].[Discriminator], [b].[Name], [b0].[Id], [b0].[Discriminator], [b0].[Name], [b0].[BaseId], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [b0].[OwnedReferenceOnDerived_Id], [b0].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name] + @"SELECT [n].[Id], [n].[Discriminator], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId], [b].[Id], [b].[BaseParentId], [b].[Discriminator], [b].[Name], [b0].[Id], [b0].[Discriminator], [b0].[Name], [b0].[BaseId], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [b0].[OwnedReferenceOnDerived_Id], [b0].[OwnedReferenceOnDerived_Name] FROM [NestedCollections] AS [n] LEFT JOIN [BaseReferencesOnBase] AS [b] ON [n].[ParentReferenceId] = [b].[Id] LEFT JOIN [BaseEntities] AS [b0] ON [b].[BaseParentId] = [b0].[Id] @@ -596,7 +596,7 @@ public override async Task Nested_include_with_inheritance_collection_reference( await base.Nested_include_with_inheritance_collection_reference(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [t].[Id], [t].[BaseParentId], [t].[Discriminator], [t].[Name], [t].[DerivedProperty], [t].[Id0], [t].[Discriminator0], [t].[Name0], [t].[ParentCollectionId], [t].[ParentReferenceId] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Discriminator], [t].[Name], [t].[DerivedProperty], [t].[Id0], [t].[Discriminator0], [t].[Name0], [t].[ParentCollectionId], [t].[ParentReferenceId] FROM [BaseEntities] AS [b] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] LEFT JOIN [BaseEntities_OwnedCollectionOnDerived] AS [b1] ON [b].[Id] = [b1].[DerivedInheritanceRelationshipEntityId] @@ -613,7 +613,7 @@ public override async Task Nested_include_with_inheritance_collection_reference_ await base.Nested_include_with_inheritance_collection_reference_reverse(async); AssertSql( - @"SELECT [n].[Id], [n].[Discriminator], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId], [b].[Id], [b].[BaseParentId], [b].[Discriminator], [b].[Name], [b].[DerivedProperty], [b0].[Id], [b0].[Discriminator], [b0].[Name], [b0].[BaseId], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [b0].[OwnedReferenceOnDerived_Id], [b0].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name] + @"SELECT [n].[Id], [n].[Discriminator], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId], [b].[Id], [b].[BaseParentId], [b].[Discriminator], [b].[Name], [b].[DerivedProperty], [b0].[Id], [b0].[Discriminator], [b0].[Name], [b0].[BaseId], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [b0].[OwnedReferenceOnDerived_Id], [b0].[OwnedReferenceOnDerived_Name] FROM [NestedReferences] AS [n] LEFT JOIN [BaseCollectionsOnBase] AS [b] ON [n].[ParentCollectionId] = [b].[Id] LEFT JOIN [BaseEntities] AS [b0] ON [b].[BaseParentId] = [b0].[Id] @@ -627,7 +627,7 @@ public override async Task Nested_include_with_inheritance_collection_collection await base.Nested_include_with_inheritance_collection_collection(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [t].[Id], [t].[BaseParentId], [t].[Discriminator], [t].[Name], [t].[DerivedProperty], [t].[Id0], [t].[Discriminator0], [t].[Name0], [t].[ParentCollectionId], [t].[ParentReferenceId] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b1].[DerivedInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Discriminator], [t].[Name], [t].[DerivedProperty], [t].[Id0], [t].[Discriminator0], [t].[Name0], [t].[ParentCollectionId], [t].[ParentReferenceId] FROM [BaseEntities] AS [b] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] LEFT JOIN [BaseEntities_OwnedCollectionOnDerived] AS [b1] ON [b].[Id] = [b1].[DerivedInheritanceRelationshipEntityId] @@ -644,7 +644,7 @@ public override async Task Nested_include_with_inheritance_collection_collection await base.Nested_include_with_inheritance_collection_collection_reverse(async); AssertSql( - @"SELECT [n].[Id], [n].[Discriminator], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId], [b].[Id], [b].[BaseParentId], [b].[Discriminator], [b].[Name], [b].[DerivedProperty], [b0].[Id], [b0].[Discriminator], [b0].[Name], [b0].[BaseId], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [b0].[OwnedReferenceOnDerived_Id], [b0].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name] + @"SELECT [n].[Id], [n].[Discriminator], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId], [b].[Id], [b].[BaseParentId], [b].[Discriminator], [b].[Name], [b].[DerivedProperty], [b0].[Id], [b0].[Discriminator], [b0].[Name], [b0].[BaseId], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [b2].[DerivedInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [b0].[OwnedReferenceOnDerived_Id], [b0].[OwnedReferenceOnDerived_Name] FROM [NestedCollections] AS [n] LEFT JOIN [BaseCollectionsOnBase] AS [b] ON [n].[ParentCollectionId] = [b].[Id] LEFT JOIN [BaseEntities] AS [b0] ON [b].[BaseParentId] = [b0].[Id] @@ -1016,7 +1016,7 @@ public override async Task Nested_include_with_inheritance_reference_collection_ await base.Nested_include_with_inheritance_reference_collection_split(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[Id], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[Id], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name] FROM [BaseEntities] AS [b] LEFT JOIN [BaseReferencesOnBase] AS [b0] ON [b].[Id] = [b0].[BaseParentId] ORDER BY [b].[Id], [b0].[Id]", @@ -1045,7 +1045,7 @@ public override async Task Nested_include_with_inheritance_reference_collection_ await base.Nested_include_with_inheritance_reference_collection_on_base_split(async); AssertSql( - @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[Id], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name] + @"SELECT [b].[Id], [b].[Discriminator], [b].[Name], [b].[BaseId], [b0].[Id], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [b].[OwnedReferenceOnDerived_Id], [b].[OwnedReferenceOnDerived_Name], [b0].[BaseParentId], [b0].[Discriminator], [b0].[Name] FROM [BaseEntities] AS [b] LEFT JOIN [BaseReferencesOnBase] AS [b0] ON [b].[Id] = [b0].[BaseParentId] WHERE [b].[Discriminator] = N'DerivedInheritanceRelationshipEntity' diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ManyToManyNoTrackingQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ManyToManyNoTrackingQuerySqlServerTest.cs index 610eb58689a..f6713f07a3b 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/ManyToManyNoTrackingQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/ManyToManyNoTrackingQuerySqlServerTest.cs @@ -645,7 +645,7 @@ public override async Task Include_skip_navigation_and_reference(bool async) await base.Include_skip_navigation_and_reference(async); AssertSql( - @"SELECT [e].[Id], [e].[CollectionInverseId], [e].[ExtraId], [e].[Name], [e].[ReferenceInverseId], [e0].[Id], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId], [t].[Id], [t].[Name], [t].[EntityOneId], [t].[EntityTwoId] + @"SELECT [e].[Id], [e].[CollectionInverseId], [e].[ExtraId], [e].[Name], [e].[ReferenceInverseId], [e0].[Id], [t].[Id], [t].[Name], [t].[EntityOneId], [t].[EntityTwoId], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId] FROM [EntityTwos] AS [e] LEFT JOIN [EntityThrees] AS [e0] ON [e].[Id] = [e0].[ReferenceInverseId] LEFT JOIN ( diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ManyToManyQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ManyToManyQuerySqlServerTest.cs index 4bb1c10a18b..eee2ea7f3fc 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/ManyToManyQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/ManyToManyQuerySqlServerTest.cs @@ -644,7 +644,7 @@ public override async Task Include_skip_navigation_and_reference(bool async) await base.Include_skip_navigation_and_reference(async); AssertSql( - @"SELECT [e].[Id], [e].[CollectionInverseId], [e].[ExtraId], [e].[Name], [e].[ReferenceInverseId], [e0].[Id], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId], [t].[EntityOneId], [t].[EntityTwoId], [t].[Id], [t].[Name] + @"SELECT [e].[Id], [e].[CollectionInverseId], [e].[ExtraId], [e].[Name], [e].[ReferenceInverseId], [e0].[Id], [t].[EntityOneId], [t].[EntityTwoId], [t].[Id], [t].[Name], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId] FROM [EntityTwos] AS [e] LEFT JOIN [EntityThrees] AS [e0] ON [e].[Id] = [e0].[ReferenceInverseId] LEFT JOIN ( diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindIncludeQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindIncludeQuerySqlServerTest.cs index 20c0302fafc..93a4ab72640 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindIncludeQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindIncludeQuerySqlServerTest.cs @@ -608,7 +608,7 @@ public override async Task Include_duplicate_collection(bool async) AssertSql( @"@__p_0='2' -SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [t0].[CustomerID], [t0].[Address], [t0].[City], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Country], [t0].[Fax], [t0].[Phone], [t0].[PostalCode], [t0].[Region], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate] +SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [t0].[CustomerID], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [t0].[Address], [t0].[City], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Country], [t0].[Fax], [t0].[Phone], [t0].[PostalCode], [t0].[Region], [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate] FROM ( SELECT TOP(@__p_0) [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] @@ -633,7 +633,7 @@ public override async Task Include_duplicate_collection_result_operator(bool asy @"@__p_1='1' @__p_0='2' -SELECT [t1].[CustomerID], [t1].[Address], [t1].[City], [t1].[CompanyName], [t1].[ContactName], [t1].[ContactTitle], [t1].[Country], [t1].[Fax], [t1].[Phone], [t1].[PostalCode], [t1].[Region], [t1].[CustomerID0], [t1].[Address0], [t1].[City0], [t1].[CompanyName0], [t1].[ContactName0], [t1].[ContactTitle0], [t1].[Country0], [t1].[Fax0], [t1].[Phone0], [t1].[PostalCode0], [t1].[Region0], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate] +SELECT [t1].[CustomerID], [t1].[Address], [t1].[City], [t1].[CompanyName], [t1].[ContactName], [t1].[ContactTitle], [t1].[Country], [t1].[Fax], [t1].[Phone], [t1].[PostalCode], [t1].[Region], [t1].[CustomerID0], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [t1].[Address0], [t1].[City0], [t1].[CompanyName0], [t1].[ContactName0], [t1].[ContactTitle0], [t1].[Country0], [t1].[Fax0], [t1].[Phone0], [t1].[PostalCode0], [t1].[Region0], [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate] FROM ( SELECT TOP(@__p_1) [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [t0].[CustomerID] AS [CustomerID0], [t0].[Address] AS [Address0], [t0].[City] AS [City0], [t0].[CompanyName] AS [CompanyName0], [t0].[ContactName] AS [ContactName0], [t0].[ContactTitle] AS [ContactTitle0], [t0].[Country] AS [Country0], [t0].[Fax] AS [Fax0], [t0].[Phone] AS [Phone0], [t0].[PostalCode] AS [PostalCode0], [t0].[Region] AS [Region0] FROM ( @@ -730,7 +730,7 @@ public override async Task Include_duplicate_collection_result_operator2(bool as @"@__p_1='1' @__p_0='2' -SELECT [t1].[CustomerID], [t1].[Address], [t1].[City], [t1].[CompanyName], [t1].[ContactName], [t1].[ContactTitle], [t1].[Country], [t1].[Fax], [t1].[Phone], [t1].[PostalCode], [t1].[Region], [t1].[CustomerID0], [t1].[Address0], [t1].[City0], [t1].[CompanyName0], [t1].[ContactName0], [t1].[ContactTitle0], [t1].[Country0], [t1].[Fax0], [t1].[Phone0], [t1].[PostalCode0], [t1].[Region0], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] +SELECT [t1].[CustomerID], [t1].[Address], [t1].[City], [t1].[CompanyName], [t1].[ContactName], [t1].[ContactTitle], [t1].[Country], [t1].[Fax], [t1].[Phone], [t1].[PostalCode], [t1].[Region], [t1].[CustomerID0], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [t1].[Address0], [t1].[City0], [t1].[CompanyName0], [t1].[ContactName0], [t1].[ContactTitle0], [t1].[Country0], [t1].[Fax0], [t1].[Phone0], [t1].[PostalCode0], [t1].[Region0] FROM ( SELECT TOP(@__p_1) [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [t0].[CustomerID] AS [CustomerID0], [t0].[Address] AS [Address0], [t0].[City] AS [City0], [t0].[CompanyName] AS [CompanyName0], [t0].[ContactName] AS [ContactName0], [t0].[ContactTitle] AS [ContactTitle0], [t0].[Country] AS [Country0], [t0].[Fax] AS [Fax0], [t0].[Phone] AS [Phone0], [t0].[PostalCode] AS [PostalCode0], [t0].[Region] AS [Region0] FROM ( @@ -1318,19 +1318,19 @@ public override async Task Include_in_let_followed_by_FirstOrDefault(bool async) await base.Include_in_let_followed_by_FirstOrDefault(async); AssertSql( - @"SELECT [c].[CustomerID], [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t0].[c], [o0].[OrderID], [o0].[ProductID], [o0].[Discount], [o0].[Quantity], [o0].[UnitPrice] + @"SELECT [c].[CustomerID], [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t0].[OrderID0], [t0].[ProductID], [t0].[Discount], [t0].[Quantity], [t0].[UnitPrice] FROM [Customers] AS [c] -LEFT JOIN ( - SELECT [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate], [t].[c] +OUTER APPLY ( + SELECT [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate], [o0].[OrderID] AS [OrderID0], [o0].[ProductID], [o0].[Discount], [o0].[Quantity], [o0].[UnitPrice] FROM ( - SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], 1 AS [c], ROW_NUMBER() OVER(PARTITION BY [o].[CustomerID] ORDER BY [o].[OrderDate]) AS [row] + SELECT TOP(1) [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] FROM [Orders] AS [o] + WHERE [o].[CustomerID] = [c].[CustomerID] + ORDER BY [o].[OrderDate] ) AS [t] - WHERE [t].[row] <= 1 -) AS [t0] ON [c].[CustomerID] = [t0].[CustomerID] -LEFT JOIN [Order Details] AS [o0] ON [t0].[OrderID] = [o0].[OrderID] -WHERE [c].[CustomerID] LIKE N'F%' -ORDER BY [c].[CustomerID], [t0].[OrderID], [o0].[OrderID], [o0].[ProductID]"); + LEFT JOIN [Order Details] AS [o0] ON [t].[OrderID] = [o0].[OrderID] +) AS [t0] +WHERE [c].[CustomerID] LIKE N'F%'"); } public override async Task Repro9735(bool async) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindJoinQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindJoinQuerySqlServerTest.cs index d895f69d5bd..51992e74621 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindJoinQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindJoinQuerySqlServerTest.cs @@ -549,7 +549,7 @@ public override async Task SelectMany_with_client_eval_with_collection_shaper(bo await base.SelectMany_with_client_eval_with_collection_shaper(async); AssertSql( - @"SELECT [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate], [t].[ContactName], [c].[CustomerID], [o0].[OrderID], [o0].[ProductID], [o0].[Discount], [o0].[Quantity], [o0].[UnitPrice] + @"SELECT [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate], [c].[CustomerID], [o0].[OrderID], [o0].[ProductID], [o0].[Discount], [o0].[Quantity], [o0].[UnitPrice], [t].[ContactName] FROM [Customers] AS [c] CROSS APPLY ( SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [c].[ContactName] diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindSelectQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindSelectQuerySqlServerTest.cs index 75e9584bd26..38366e2e622 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindSelectQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindSelectQuerySqlServerTest.cs @@ -1418,7 +1418,7 @@ public override async Task Projecting_multiple_collection_with_same_constant_wor await base.Projecting_multiple_collection_with_same_constant_works(async); AssertSql( - @"SELECT [c].[CustomerID], 1 AS [Value], [o].[OrderID], [o0].[OrderID] + @"SELECT [c].[CustomerID], 1, [o].[OrderID], [o0].[OrderID] FROM [Customers] AS [c] LEFT JOIN [Orders] AS [o] ON [c].[CustomerID] = [o].[CustomerID] LEFT JOIN [Orders] AS [o0] ON [c].[CustomerID] = [o0].[CustomerID] @@ -1535,23 +1535,23 @@ public override async Task Do_not_erase_projection_mapping_when_adding_single_pr await base.Do_not_erase_projection_mapping_when_adding_single_projection(async); AssertSql( - @"SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [t0].[OrderID], [t0].[ProductID], [t0].[Discount], [t0].[Quantity], [t0].[UnitPrice], [t0].[ProductID0], [t0].[Discontinued], [t0].[ProductName], [t0].[SupplierID], [t0].[UnitPrice0], [t0].[UnitsInStock], [t0].[c], [t1].[OrderID], [t1].[ProductID], [t1].[Discount], [t1].[Quantity], [t1].[UnitPrice], [t1].[ProductID0], [t1].[Discontinued], [t1].[ProductName], [t1].[SupplierID], [t1].[UnitPrice0], [t1].[UnitsInStock], [t2].[OrderID], [t2].[ProductID], [t2].[Discount], [t2].[Quantity], [t2].[UnitPrice], [t2].[ProductID0], [t2].[Discontinued], [t2].[ProductName], [t2].[SupplierID], [t2].[UnitPrice0], [t2].[UnitsInStock] + @"SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [t].[OrderID], [t].[ProductID], [t].[Discount], [t].[Quantity], [t].[UnitPrice], [t].[ProductID0], [t].[Discontinued], [t].[ProductName], [t].[SupplierID], [t].[UnitPrice0], [t].[UnitsInStock], [t0].[OrderID], [t0].[ProductID], [t0].[Discount], [t0].[Quantity], [t0].[UnitPrice], [t0].[ProductID0], [t0].[Discontinued], [t0].[ProductName], [t0].[SupplierID], [t0].[UnitPrice0], [t0].[UnitsInStock], [t2].[OrderID], [t2].[ProductID], [t2].[Discount], [t2].[Quantity], [t2].[UnitPrice], [t2].[ProductID0], [t2].[Discontinued], [t2].[ProductName], [t2].[SupplierID], [t2].[UnitPrice0], [t2].[UnitsInStock] FROM [Orders] AS [o] LEFT JOIN ( - SELECT [t].[OrderID], [t].[ProductID], [t].[Discount], [t].[Quantity], [t].[UnitPrice], [t].[ProductID0], [t].[Discontinued], [t].[ProductName], [t].[SupplierID], [t].[UnitPrice0], [t].[UnitsInStock], [t].[c] + SELECT [o0].[OrderID], [o0].[ProductID], [o0].[Discount], [o0].[Quantity], [o0].[UnitPrice], [p].[ProductID] AS [ProductID0], [p].[Discontinued], [p].[ProductName], [p].[SupplierID], [p].[UnitPrice] AS [UnitPrice0], [p].[UnitsInStock] + FROM [Order Details] AS [o0] + INNER JOIN [Products] AS [p] ON [o0].[ProductID] = [p].[ProductID] +) AS [t] ON [o].[OrderID] = [t].[OrderID] +LEFT JOIN ( + SELECT [t1].[OrderID], [t1].[ProductID], [t1].[Discount], [t1].[Quantity], [t1].[UnitPrice], [t1].[ProductID0], [t1].[Discontinued], [t1].[ProductName], [t1].[SupplierID], [t1].[UnitPrice0], [t1].[UnitsInStock] FROM ( - SELECT [o0].[OrderID], [o0].[ProductID], [o0].[Discount], [o0].[Quantity], [o0].[UnitPrice], [p].[ProductID] AS [ProductID0], [p].[Discontinued], [p].[ProductName], [p].[SupplierID], [p].[UnitPrice] AS [UnitPrice0], [p].[UnitsInStock], 1 AS [c], ROW_NUMBER() OVER(PARTITION BY [o0].[OrderID] ORDER BY [o0].[OrderID], [o0].[ProductID], [p].[ProductID]) AS [row] - FROM [Order Details] AS [o0] - INNER JOIN [Products] AS [p] ON [o0].[ProductID] = [p].[ProductID] - WHERE [o0].[UnitPrice] > 10.0 - ) AS [t] - WHERE [t].[row] <= 1 + SELECT [o1].[OrderID], [o1].[ProductID], [o1].[Discount], [o1].[Quantity], [o1].[UnitPrice], [p0].[ProductID] AS [ProductID0], [p0].[Discontinued], [p0].[ProductName], [p0].[SupplierID], [p0].[UnitPrice] AS [UnitPrice0], [p0].[UnitsInStock], ROW_NUMBER() OVER(PARTITION BY [o1].[OrderID] ORDER BY [o1].[OrderID], [o1].[ProductID], [p0].[ProductID]) AS [row] + FROM [Order Details] AS [o1] + INNER JOIN [Products] AS [p0] ON [o1].[ProductID] = [p0].[ProductID] + WHERE [o1].[UnitPrice] > 10.0 + ) AS [t1] + WHERE [t1].[row] <= 1 ) AS [t0] ON [o].[OrderID] = [t0].[OrderID] -LEFT JOIN ( - SELECT [o1].[OrderID], [o1].[ProductID], [o1].[Discount], [o1].[Quantity], [o1].[UnitPrice], [p0].[ProductID] AS [ProductID0], [p0].[Discontinued], [p0].[ProductName], [p0].[SupplierID], [p0].[UnitPrice] AS [UnitPrice0], [p0].[UnitsInStock] - FROM [Order Details] AS [o1] - INNER JOIN [Products] AS [p0] ON [o1].[ProductID] = [p0].[ProductID] -) AS [t1] ON [o].[OrderID] = [t1].[OrderID] LEFT JOIN ( SELECT [o2].[OrderID], [o2].[ProductID], [o2].[Discount], [o2].[Quantity], [o2].[UnitPrice], [p1].[ProductID] AS [ProductID0], [p1].[Discontinued], [p1].[ProductName], [p1].[SupplierID], [p1].[UnitPrice] AS [UnitPrice0], [p1].[UnitsInStock] FROM [Order Details] AS [o2] @@ -1559,7 +1559,7 @@ FROM [Order Details] AS [o2] WHERE [o2].[UnitPrice] < 10.0 ) AS [t2] ON [o].[OrderID] = [t2].[OrderID] WHERE [o].[OrderID] < 10350 -ORDER BY [o].[OrderID], [t0].[OrderID], [t0].[ProductID], [t0].[ProductID0], [t1].[OrderID], [t1].[ProductID], [t1].[ProductID0], [t2].[OrderID], [t2].[ProductID], [t2].[ProductID0]"); +ORDER BY [o].[OrderID], [t].[OrderID], [t].[ProductID], [t].[ProductID0], [t0].[OrderID], [t0].[ProductID], [t0].[ProductID0], [t2].[OrderID], [t2].[ProductID], [t2].[ProductID0]"); } public override async Task Ternary_in_client_eval_assigns_correct_types(bool async) @@ -1724,24 +1724,25 @@ public override async Task Collection_include_over_result_of_single_non_scalar(b await base.Collection_include_over_result_of_single_non_scalar(async); AssertSql( - @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region], [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t0].[c], [t1].[OrderID], [t1].[CustomerID], [t1].[EmployeeID], [t1].[OrderDate], [t1].[OrderID0], [t1].[ProductID], [t1].[Discount], [t1].[Quantity], [t1].[UnitPrice], [o2].[OrderID], [o2].[ProductID], [o2].[Discount], [o2].[Quantity], [o2].[UnitPrice] + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region], [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate], [t].[OrderID0], [t].[ProductID], [t].[Discount], [t].[Quantity], [t].[UnitPrice], [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t0].[OrderID0], [t0].[ProductID], [t0].[Discount], [t0].[Quantity], [t0].[UnitPrice] FROM [Customers] AS [c] LEFT JOIN ( - SELECT [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate], [t].[c] + SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [o0].[OrderID] AS [OrderID0], [o0].[ProductID], [o0].[Discount], [o0].[Quantity], [o0].[UnitPrice] + FROM [Orders] AS [o] + LEFT JOIN [Order Details] AS [o0] ON [o].[OrderID] = [o0].[OrderID] +) AS [t] ON [c].[CustomerID] = [t].[CustomerID] +OUTER APPLY ( + SELECT [t1].[OrderID], [t1].[CustomerID], [t1].[EmployeeID], [t1].[OrderDate], [o1].[OrderID] AS [OrderID0], [o1].[ProductID], [o1].[Discount], [o1].[Quantity], [o1].[UnitPrice] FROM ( - SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], 1 AS [c], ROW_NUMBER() OVER(PARTITION BY [o].[CustomerID] ORDER BY [o].[OrderDate]) AS [row] - FROM [Orders] AS [o] - ) AS [t] - WHERE [t].[row] <= 1 -) AS [t0] ON [c].[CustomerID] = [t0].[CustomerID] -LEFT JOIN ( - SELECT [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate], [o1].[OrderID] AS [OrderID0], [o1].[ProductID], [o1].[Discount], [o1].[Quantity], [o1].[UnitPrice] - FROM [Orders] AS [o0] - LEFT JOIN [Order Details] AS [o1] ON [o0].[OrderID] = [o1].[OrderID] -) AS [t1] ON [c].[CustomerID] = [t1].[CustomerID] -LEFT JOIN [Order Details] AS [o2] ON [t0].[OrderID] = [o2].[OrderID] + SELECT TOP(1) [o2].[OrderID], [o2].[CustomerID], [o2].[EmployeeID], [o2].[OrderDate] + FROM [Orders] AS [o2] + WHERE [c].[CustomerID] = [o2].[CustomerID] + ORDER BY [o2].[OrderDate] + ) AS [t1] + LEFT JOIN [Order Details] AS [o1] ON [t1].[OrderID] = [o1].[OrderID] +) AS [t0] WHERE [c].[CustomerID] LIKE N'F%' -ORDER BY [c].[CustomerID], [t0].[OrderID], [t1].[OrderID], [t1].[OrderID0], [t1].[ProductID], [o2].[OrderID], [o2].[ProductID]"); +ORDER BY [c].[CustomerID], [t].[OrderID], [t].[OrderID0], [t].[ProductID]"); } public override async Task Collection_projection_selecting_outer_element_followed_by_take(bool async) @@ -1776,7 +1777,7 @@ public override async Task Take_on_top_level_and_on_collection_projection_with_o await base.Take_on_top_level_and_on_collection_projection_with_outer_apply(async); AssertSql( - @"SELECT [t].[OrderID], [t].[OrderDate], [t0].[OrderID], [t0].[ProductID], [t0].[Discontinued], [t0].[ProductName], [t0].[SupplierID], [t0].[UnitPrice], [t0].[UnitsInStock], [t0].[UnitPrice0] AS [UnitPrice], [t0].[ProductID0] + @"SELECT [t].[OrderID], [t].[OrderDate], [t0].[OrderID], [t0].[ProductID], [t0].[Discontinued], [t0].[ProductName], [t0].[SupplierID], [t0].[UnitPrice], [t0].[UnitsInStock], [t0].[UnitPrice0], [t0].[ProductID0] FROM ( SELECT TOP(1) [o].[OrderID], [o].[OrderDate] FROM [Orders] AS [o] diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/OwnedQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/OwnedQuerySqlServerTest.cs index ebd4b5a011a..fcbccef66a4 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/OwnedQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/OwnedQuerySqlServerTest.cs @@ -23,7 +23,7 @@ public override async Task Query_with_owned_entity_equality_operator(bool async) await base.Query_with_owned_entity_equality_operator(async); AssertSql( - @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId], [t].[Id], [t0].[ClientId], [t0].[Id], [t0].[OrderDate], [t0].[OrderClientId], [t0].[OrderId], [t0].[Id0], [t0].[Detail] + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [t].[Id], [t0].[ClientId], [t0].[Id], [t0].[OrderDate], [t0].[OrderClientId], [t0].[OrderId], [t0].[Id0], [t0].[Detail], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] FROM [OwnedPerson] AS [o] CROSS JOIN ( SELECT [o0].[Id] @@ -45,7 +45,7 @@ public override async Task Query_for_base_type_loads_all_owned_navs(bool async) // See issue #10067 AssertSql( - @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail] + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] FROM [OwnedPerson] AS [o] LEFT JOIN ( SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail] @@ -69,7 +69,7 @@ public override async Task Query_for_branch_type_loads_all_owned_navs(bool async await base.Query_for_branch_type_loads_all_owned_navs(async); AssertSql( - @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail] + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] FROM [OwnedPerson] AS [o] LEFT JOIN ( SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail] @@ -85,7 +85,7 @@ public override async Task Query_for_branch_type_loads_all_owned_navs_tracking(b await base.Query_for_branch_type_loads_all_owned_navs_tracking(async); AssertSql( - @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail] + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] FROM [OwnedPerson] AS [o] LEFT JOIN ( SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail] @@ -101,7 +101,7 @@ public override async Task Query_for_leaf_type_loads_all_owned_navs(bool async) await base.Query_for_leaf_type_loads_all_owned_navs(async); AssertSql( - @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail] + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] FROM [OwnedPerson] AS [o] LEFT JOIN ( SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail] @@ -119,7 +119,7 @@ public override async Task Query_when_subquery(bool async) AssertSql( @"@__p_0='5' -SELECT [t0].[Id], [t0].[Discriminator], [t0].[Name], [t0].[PersonAddress_AddressLine], [t0].[PersonAddress_PlaceType], [t0].[PersonAddress_ZipCode], [t0].[PersonAddress_Country_Name], [t0].[PersonAddress_Country_PlanetId], [t0].[BranchAddress_BranchName], [t0].[BranchAddress_PlaceType], [t0].[BranchAddress_Country_Name], [t0].[BranchAddress_Country_PlanetId], [t0].[LeafBAddress_LeafBType], [t0].[LeafBAddress_PlaceType], [t0].[LeafBAddress_Country_Name], [t0].[LeafBAddress_Country_PlanetId], [t0].[LeafAAddress_LeafType], [t0].[LeafAAddress_PlaceType], [t0].[LeafAAddress_Country_Name], [t0].[LeafAAddress_Country_PlanetId], [t1].[ClientId], [t1].[Id], [t1].[OrderDate], [t1].[OrderClientId], [t1].[OrderId], [t1].[Id0], [t1].[Detail] +SELECT [t0].[Id], [t0].[Discriminator], [t0].[Name], [t1].[ClientId], [t1].[Id], [t1].[OrderDate], [t1].[OrderClientId], [t1].[OrderId], [t1].[Id0], [t1].[Detail], [t0].[PersonAddress_AddressLine], [t0].[PersonAddress_PlaceType], [t0].[PersonAddress_ZipCode], [t0].[PersonAddress_Country_Name], [t0].[PersonAddress_Country_PlanetId], [t0].[BranchAddress_BranchName], [t0].[BranchAddress_PlaceType], [t0].[BranchAddress_Country_Name], [t0].[BranchAddress_Country_PlanetId], [t0].[LeafBAddress_LeafBType], [t0].[LeafBAddress_PlaceType], [t0].[LeafBAddress_Country_Name], [t0].[LeafBAddress_Country_PlanetId], [t0].[LeafAAddress_LeafType], [t0].[LeafAAddress_PlaceType], [t0].[LeafAAddress_Country_Name], [t0].[LeafAAddress_Country_PlanetId] FROM ( SELECT TOP(@__p_0) [t].[Id], [t].[Discriminator], [t].[Name], [t].[PersonAddress_AddressLine], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[PersonAddress_Country_Name], [t].[PersonAddress_Country_PlanetId], [t].[BranchAddress_BranchName], [t].[BranchAddress_PlaceType], [t].[BranchAddress_Country_Name], [t].[BranchAddress_Country_PlanetId], [t].[LeafBAddress_LeafBType], [t].[LeafBAddress_PlaceType], [t].[LeafBAddress_Country_Name], [t].[LeafBAddress_Country_PlanetId], [t].[LeafAAddress_LeafType], [t].[LeafAAddress_PlaceType], [t].[LeafAAddress_Country_Name], [t].[LeafAAddress_Country_PlanetId] FROM ( @@ -151,7 +151,7 @@ public override async Task Navigation_rewrite_on_owned_reference_projecting_enti await base.Navigation_rewrite_on_owned_reference_projecting_entity(async); AssertSql( - @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail] + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] FROM [OwnedPerson] AS [o] LEFT JOIN ( SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail] @@ -256,7 +256,7 @@ public override async Task Project_multiple_owned_navigations(bool async) await base.Project_multiple_owned_navigations(async); AssertSql( - @"SELECT [o].[Id], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [p].[Id], [p].[StarId], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail] + @"SELECT [o].[Id], [p].[Id], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [p].[StarId] FROM [OwnedPerson] AS [o] LEFT JOIN [Planet] AS [p] ON [o].[PersonAddress_Country_PlanetId] = [p].[Id] LEFT JOIN ( @@ -289,7 +289,7 @@ public override async Task Navigation_rewrite_on_owned_reference_followed_by_reg await base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_filter(async); AssertSql( - @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId], [p].[Id], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail] + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [p].[Id], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] FROM [OwnedPerson] AS [o] LEFT JOIN [Planet] AS [p] ON [o].[PersonAddress_Country_PlanetId] = [p].[Id] LEFT JOIN ( @@ -392,7 +392,7 @@ public override async Task Query_with_OfType_eagerly_loads_correct_owned_navigat await base.Query_with_OfType_eagerly_loads_correct_owned_navigations(async); AssertSql( - @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail] + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] FROM [OwnedPerson] AS [o] LEFT JOIN ( SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail] @@ -414,7 +414,7 @@ public override async Task Preserve_includes_when_applying_skip_take_after_anony @"@__p_1='0' @__p_2='100' -SELECT [t].[Id], [t].[Discriminator], [t].[Name], [t].[PersonAddress_AddressLine], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[PersonAddress_Country_Name], [t].[PersonAddress_Country_PlanetId], [t].[BranchAddress_BranchName], [t].[BranchAddress_PlaceType], [t].[BranchAddress_Country_Name], [t].[BranchAddress_Country_PlanetId], [t].[LeafBAddress_LeafBType], [t].[LeafBAddress_PlaceType], [t].[LeafBAddress_Country_Name], [t].[LeafBAddress_Country_PlanetId], [t].[LeafAAddress_LeafType], [t].[LeafAAddress_PlaceType], [t].[LeafAAddress_Country_Name], [t].[LeafAAddress_Country_PlanetId], [t0].[ClientId], [t0].[Id], [t0].[OrderDate], [t0].[OrderClientId], [t0].[OrderId], [t0].[Id0], [t0].[Detail] +SELECT [t].[Id], [t].[Discriminator], [t].[Name], [t0].[ClientId], [t0].[Id], [t0].[OrderDate], [t0].[OrderClientId], [t0].[OrderId], [t0].[Id0], [t0].[Detail], [t].[PersonAddress_AddressLine], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[PersonAddress_Country_Name], [t].[PersonAddress_Country_PlanetId], [t].[BranchAddress_BranchName], [t].[BranchAddress_PlaceType], [t].[BranchAddress_Country_Name], [t].[BranchAddress_Country_PlanetId], [t].[LeafBAddress_LeafBType], [t].[LeafBAddress_PlaceType], [t].[LeafBAddress_Country_Name], [t].[LeafBAddress_Country_PlanetId], [t].[LeafAAddress_LeafType], [t].[LeafAAddress_PlaceType], [t].[LeafAAddress_Country_Name], [t].[LeafAAddress_Country_PlanetId] FROM ( SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] FROM [OwnedPerson] AS [o] @@ -434,7 +434,7 @@ public override async Task Unmapped_property_projection_loads_owned_navigations( await base.Unmapped_property_projection_loads_owned_navigations(async); AssertSql( - @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail] + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] FROM [OwnedPerson] AS [o] LEFT JOIN ( SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail] @@ -452,7 +452,7 @@ public override async Task Client_method_skip_loads_owned_navigations(bool async AssertSql( @"@__p_0='1' -SELECT [t].[Id], [t].[Discriminator], [t].[Name], [t].[PersonAddress_AddressLine], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[PersonAddress_Country_Name], [t].[PersonAddress_Country_PlanetId], [t].[BranchAddress_BranchName], [t].[BranchAddress_PlaceType], [t].[BranchAddress_Country_Name], [t].[BranchAddress_Country_PlanetId], [t].[LeafBAddress_LeafBType], [t].[LeafBAddress_PlaceType], [t].[LeafBAddress_Country_Name], [t].[LeafBAddress_Country_PlanetId], [t].[LeafAAddress_LeafType], [t].[LeafAAddress_PlaceType], [t].[LeafAAddress_Country_Name], [t].[LeafAAddress_Country_PlanetId], [t0].[ClientId], [t0].[Id], [t0].[OrderDate], [t0].[OrderClientId], [t0].[OrderId], [t0].[Id0], [t0].[Detail] +SELECT [t].[Id], [t].[Discriminator], [t].[Name], [t0].[ClientId], [t0].[Id], [t0].[OrderDate], [t0].[OrderClientId], [t0].[OrderId], [t0].[Id0], [t0].[Detail], [t].[PersonAddress_AddressLine], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[PersonAddress_Country_Name], [t].[PersonAddress_Country_PlanetId], [t].[BranchAddress_BranchName], [t].[BranchAddress_PlaceType], [t].[BranchAddress_Country_Name], [t].[BranchAddress_Country_PlanetId], [t].[LeafBAddress_LeafBType], [t].[LeafBAddress_PlaceType], [t].[LeafBAddress_Country_Name], [t].[LeafBAddress_Country_PlanetId], [t].[LeafAAddress_LeafType], [t].[LeafAAddress_PlaceType], [t].[LeafAAddress_Country_Name], [t].[LeafAAddress_Country_PlanetId] FROM ( SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] FROM [OwnedPerson] AS [o] @@ -474,7 +474,7 @@ public override async Task Client_method_take_loads_owned_navigations(bool async AssertSql( @"@__p_0='2' -SELECT [t].[Id], [t].[Discriminator], [t].[Name], [t].[PersonAddress_AddressLine], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[PersonAddress_Country_Name], [t].[PersonAddress_Country_PlanetId], [t].[BranchAddress_BranchName], [t].[BranchAddress_PlaceType], [t].[BranchAddress_Country_Name], [t].[BranchAddress_Country_PlanetId], [t].[LeafBAddress_LeafBType], [t].[LeafBAddress_PlaceType], [t].[LeafBAddress_Country_Name], [t].[LeafBAddress_Country_PlanetId], [t].[LeafAAddress_LeafType], [t].[LeafAAddress_PlaceType], [t].[LeafAAddress_Country_Name], [t].[LeafAAddress_Country_PlanetId], [t0].[ClientId], [t0].[Id], [t0].[OrderDate], [t0].[OrderClientId], [t0].[OrderId], [t0].[Id0], [t0].[Detail] +SELECT [t].[Id], [t].[Discriminator], [t].[Name], [t0].[ClientId], [t0].[Id], [t0].[OrderDate], [t0].[OrderClientId], [t0].[OrderId], [t0].[Id0], [t0].[Detail], [t].[PersonAddress_AddressLine], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[PersonAddress_Country_Name], [t].[PersonAddress_Country_PlanetId], [t].[BranchAddress_BranchName], [t].[BranchAddress_PlaceType], [t].[BranchAddress_Country_Name], [t].[BranchAddress_Country_PlanetId], [t].[LeafBAddress_LeafBType], [t].[LeafBAddress_PlaceType], [t].[LeafBAddress_Country_Name], [t].[LeafBAddress_Country_PlanetId], [t].[LeafAAddress_LeafType], [t].[LeafAAddress_PlaceType], [t].[LeafAAddress_Country_Name], [t].[LeafAAddress_Country_PlanetId] FROM ( SELECT TOP(@__p_0) [o].[Id], [o].[Discriminator], [o].[Name], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] FROM [OwnedPerson] AS [o] @@ -496,7 +496,7 @@ public override async Task Client_method_skip_take_loads_owned_navigations(bool @"@__p_0='1' @__p_1='2' -SELECT [t].[Id], [t].[Discriminator], [t].[Name], [t].[PersonAddress_AddressLine], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[PersonAddress_Country_Name], [t].[PersonAddress_Country_PlanetId], [t].[BranchAddress_BranchName], [t].[BranchAddress_PlaceType], [t].[BranchAddress_Country_Name], [t].[BranchAddress_Country_PlanetId], [t].[LeafBAddress_LeafBType], [t].[LeafBAddress_PlaceType], [t].[LeafBAddress_Country_Name], [t].[LeafBAddress_Country_PlanetId], [t].[LeafAAddress_LeafType], [t].[LeafAAddress_PlaceType], [t].[LeafAAddress_Country_Name], [t].[LeafAAddress_Country_PlanetId], [t0].[ClientId], [t0].[Id], [t0].[OrderDate], [t0].[OrderClientId], [t0].[OrderId], [t0].[Id0], [t0].[Detail] +SELECT [t].[Id], [t].[Discriminator], [t].[Name], [t0].[ClientId], [t0].[Id], [t0].[OrderDate], [t0].[OrderClientId], [t0].[OrderId], [t0].[Id0], [t0].[Detail], [t].[PersonAddress_AddressLine], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[PersonAddress_Country_Name], [t].[PersonAddress_Country_PlanetId], [t].[BranchAddress_BranchName], [t].[BranchAddress_PlaceType], [t].[BranchAddress_Country_Name], [t].[BranchAddress_Country_PlanetId], [t].[LeafBAddress_LeafBType], [t].[LeafBAddress_PlaceType], [t].[LeafBAddress_Country_Name], [t].[LeafBAddress_Country_PlanetId], [t].[LeafAAddress_LeafType], [t].[LeafAAddress_PlaceType], [t].[LeafAAddress_Country_Name], [t].[LeafAAddress_Country_PlanetId] FROM ( SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] FROM [OwnedPerson] AS [o] @@ -518,7 +518,7 @@ public override async Task Client_method_skip_loads_owned_navigations_variation_ AssertSql( @"@__p_0='1' -SELECT [t].[Id], [t].[Discriminator], [t].[Name], [t].[PersonAddress_AddressLine], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[PersonAddress_Country_Name], [t].[PersonAddress_Country_PlanetId], [t].[BranchAddress_BranchName], [t].[BranchAddress_PlaceType], [t].[BranchAddress_Country_Name], [t].[BranchAddress_Country_PlanetId], [t].[LeafBAddress_LeafBType], [t].[LeafBAddress_PlaceType], [t].[LeafBAddress_Country_Name], [t].[LeafBAddress_Country_PlanetId], [t].[LeafAAddress_LeafType], [t].[LeafAAddress_PlaceType], [t].[LeafAAddress_Country_Name], [t].[LeafAAddress_Country_PlanetId], [t0].[ClientId], [t0].[Id], [t0].[OrderDate], [t0].[OrderClientId], [t0].[OrderId], [t0].[Id0], [t0].[Detail] +SELECT [t].[Id], [t].[Discriminator], [t].[Name], [t0].[ClientId], [t0].[Id], [t0].[OrderDate], [t0].[OrderClientId], [t0].[OrderId], [t0].[Id0], [t0].[Detail], [t].[PersonAddress_AddressLine], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[PersonAddress_Country_Name], [t].[PersonAddress_Country_PlanetId], [t].[BranchAddress_BranchName], [t].[BranchAddress_PlaceType], [t].[BranchAddress_Country_Name], [t].[BranchAddress_Country_PlanetId], [t].[LeafBAddress_LeafBType], [t].[LeafBAddress_PlaceType], [t].[LeafBAddress_Country_Name], [t].[LeafBAddress_Country_PlanetId], [t].[LeafAAddress_LeafType], [t].[LeafAAddress_PlaceType], [t].[LeafAAddress_Country_Name], [t].[LeafAAddress_Country_PlanetId] FROM ( SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] FROM [OwnedPerson] AS [o] @@ -540,7 +540,7 @@ public override async Task Client_method_take_loads_owned_navigations_variation_ AssertSql( @"@__p_0='2' -SELECT [t].[Id], [t].[Discriminator], [t].[Name], [t].[PersonAddress_AddressLine], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[PersonAddress_Country_Name], [t].[PersonAddress_Country_PlanetId], [t].[BranchAddress_BranchName], [t].[BranchAddress_PlaceType], [t].[BranchAddress_Country_Name], [t].[BranchAddress_Country_PlanetId], [t].[LeafBAddress_LeafBType], [t].[LeafBAddress_PlaceType], [t].[LeafBAddress_Country_Name], [t].[LeafBAddress_Country_PlanetId], [t].[LeafAAddress_LeafType], [t].[LeafAAddress_PlaceType], [t].[LeafAAddress_Country_Name], [t].[LeafAAddress_Country_PlanetId], [t0].[ClientId], [t0].[Id], [t0].[OrderDate], [t0].[OrderClientId], [t0].[OrderId], [t0].[Id0], [t0].[Detail] +SELECT [t].[Id], [t].[Discriminator], [t].[Name], [t0].[ClientId], [t0].[Id], [t0].[OrderDate], [t0].[OrderClientId], [t0].[OrderId], [t0].[Id0], [t0].[Detail], [t].[PersonAddress_AddressLine], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[PersonAddress_Country_Name], [t].[PersonAddress_Country_PlanetId], [t].[BranchAddress_BranchName], [t].[BranchAddress_PlaceType], [t].[BranchAddress_Country_Name], [t].[BranchAddress_Country_PlanetId], [t].[LeafBAddress_LeafBType], [t].[LeafBAddress_PlaceType], [t].[LeafBAddress_Country_Name], [t].[LeafBAddress_Country_PlanetId], [t].[LeafAAddress_LeafType], [t].[LeafAAddress_PlaceType], [t].[LeafAAddress_Country_Name], [t].[LeafAAddress_Country_PlanetId] FROM ( SELECT TOP(@__p_0) [o].[Id], [o].[Discriminator], [o].[Name], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] FROM [OwnedPerson] AS [o] @@ -562,7 +562,7 @@ public override async Task Client_method_skip_take_loads_owned_navigations_varia @"@__p_0='1' @__p_1='2' -SELECT [t].[Id], [t].[Discriminator], [t].[Name], [t].[PersonAddress_AddressLine], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[PersonAddress_Country_Name], [t].[PersonAddress_Country_PlanetId], [t].[BranchAddress_BranchName], [t].[BranchAddress_PlaceType], [t].[BranchAddress_Country_Name], [t].[BranchAddress_Country_PlanetId], [t].[LeafBAddress_LeafBType], [t].[LeafBAddress_PlaceType], [t].[LeafBAddress_Country_Name], [t].[LeafBAddress_Country_PlanetId], [t].[LeafAAddress_LeafType], [t].[LeafAAddress_PlaceType], [t].[LeafAAddress_Country_Name], [t].[LeafAAddress_Country_PlanetId], [t0].[ClientId], [t0].[Id], [t0].[OrderDate], [t0].[OrderClientId], [t0].[OrderId], [t0].[Id0], [t0].[Detail] +SELECT [t].[Id], [t].[Discriminator], [t].[Name], [t0].[ClientId], [t0].[Id], [t0].[OrderDate], [t0].[OrderClientId], [t0].[OrderId], [t0].[Id0], [t0].[Detail], [t].[PersonAddress_AddressLine], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[PersonAddress_Country_Name], [t].[PersonAddress_Country_PlanetId], [t].[BranchAddress_BranchName], [t].[BranchAddress_PlaceType], [t].[BranchAddress_Country_Name], [t].[BranchAddress_Country_PlanetId], [t].[LeafBAddress_LeafBType], [t].[LeafBAddress_PlaceType], [t].[LeafBAddress_Country_Name], [t].[LeafBAddress_Country_PlanetId], [t].[LeafAAddress_LeafType], [t].[LeafAAddress_PlaceType], [t].[LeafAAddress_Country_Name], [t].[LeafAAddress_Country_PlanetId] FROM ( SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] FROM [OwnedPerson] AS [o] @@ -662,7 +662,7 @@ public override async Task Can_query_on_indexer_properties(bool async) await base.Can_query_on_indexer_properties(async); AssertSql( - @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail] + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] FROM [OwnedPerson] AS [o] LEFT JOIN ( SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail] @@ -734,7 +734,7 @@ public override async Task Can_OrderBy_indexer_properties(bool async) await base.Can_OrderBy_indexer_properties(async); AssertSql( - @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail] + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] FROM [OwnedPerson] AS [o] LEFT JOIN ( SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail] @@ -966,7 +966,7 @@ public override async Task Project_multiple_owned_navigations_split(bool async) await base.Project_multiple_owned_navigations_split(async); AssertSql( - @"SELECT [o].[Id], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [p].[Id], [p].[StarId] + @"SELECT [o].[Id], [p].[Id], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [p].[StarId] FROM [OwnedPerson] AS [o] LEFT JOIN [Planet] AS [p] ON [o].[PersonAddress_Country_PlanetId] = [p].[Id] ORDER BY [o].[Id], [p].[Id]", @@ -1090,7 +1090,7 @@ public override async Task Ordering_by_identifying_projection(bool async) await base.Ordering_by_identifying_projection(async); AssertSql( - @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail] + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] FROM [OwnedPerson] AS [o] LEFT JOIN ( SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail] @@ -1105,7 +1105,7 @@ public override async Task Using_from_sql_on_owner_generates_join_with_table_for await base.Using_from_sql_on_owner_generates_join_with_table_for_owned_shared_dependents(async); AssertSql( - @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [t].[Id], [t].[PersonAddress_AddressLine], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[Id1], [t].[PersonAddress_Country_Name], [t].[PersonAddress_Country_PlanetId], [t0].[Id], [t0].[BranchAddress_BranchName], [t0].[BranchAddress_PlaceType], [t0].[Id1], [t0].[BranchAddress_Country_Name], [t0].[BranchAddress_Country_PlanetId], [t2].[Id], [t2].[LeafBAddress_LeafBType], [t2].[LeafBAddress_PlaceType], [t2].[Id1], [t2].[LeafBAddress_Country_Name], [t2].[LeafBAddress_Country_PlanetId], [t4].[Id], [t4].[LeafAAddress_LeafType], [t4].[LeafAAddress_PlaceType], [t4].[Id1], [t4].[LeafAAddress_Country_Name], [t4].[LeafAAddress_Country_PlanetId], [t].[Id0], [t0].[Id0], [t2].[Id0], [t4].[Id0], [t6].[ClientId], [t6].[Id], [t6].[OrderDate], [t6].[OrderClientId], [t6].[OrderId], [t6].[Id0], [t6].[Detail] + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0], [t2].[Id], [t2].[Id0], [t4].[Id], [t4].[Id0], [t6].[ClientId], [t6].[Id], [t6].[OrderDate], [t6].[OrderClientId], [t6].[OrderId], [t6].[Id0], [t6].[Detail], [t].[PersonAddress_AddressLine], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[Id1], [t].[PersonAddress_Country_Name], [t].[PersonAddress_Country_PlanetId], [t0].[BranchAddress_BranchName], [t0].[BranchAddress_PlaceType], [t0].[Id1], [t0].[BranchAddress_Country_Name], [t0].[BranchAddress_Country_PlanetId], [t2].[LeafBAddress_LeafBType], [t2].[LeafBAddress_PlaceType], [t2].[Id1], [t2].[LeafBAddress_Country_Name], [t2].[LeafBAddress_Country_PlanetId], [t4].[LeafAAddress_LeafType], [t4].[LeafAAddress_PlaceType], [t4].[Id1], [t4].[LeafAAddress_Country_Name], [t4].[LeafAAddress_Country_PlanetId] FROM ( SELECT * FROM ""OwnedPerson"" ) AS [o] diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs index 9e03f2fa80f..64cb05a93ae 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs @@ -1752,11 +1752,11 @@ public virtual async Task Enum_has_flag_applies_explicit_cast_for_constant() @"SELECT [e].[Id], [e].[Permission], [e].[PermissionByte], [e].[PermissionShort] FROM [Entity] AS [e] WHERE ([e].[Permission] & CAST(17179869184 AS bigint)) = CAST(17179869184 AS bigint)"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); var query = context.Entity.Where(e => e.PermissionShort.HasFlag(MyContext8538.PermissionShort.READ_WRITE)).ToList(); Assert.Single(query); @@ -1783,11 +1783,11 @@ public virtual async Task Enum_has_flag_does_not_apply_explicit_cast_for_non_con @"SELECT [e].[Id], [e].[Permission], [e].[PermissionByte], [e].[PermissionShort] FROM [Entity] AS [e] WHERE ([e].[Permission] & [e].[Permission]) = [e].[Permission]"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); var query = context.Entity.Where(e => e.PermissionByte.HasFlag(e.PermissionByte)).ToList(); Assert.Equal(3, query.Count); @@ -1900,11 +1900,11 @@ FROM [Entities] AS [e] SELECT [e].[Id], [e].[Name] FROM [Entities] AS [e] WHERE [e].[Id] = @__id_0"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); context.Cache.Compact(1); var id = 0; @@ -1931,11 +1931,11 @@ FROM [Entities] AS [e] SELECT [e].[Id], [e].[Name] FROM [Entities] AS [e] WHERE [e].[Id] = @__id_0"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); context.Cache.Compact(1); var id = 0; @@ -2217,11 +2217,11 @@ public async Task Default_schema_applied_when_no_function_schema() @"SELECT TOP(2) [foo].[AddOne]([w].[Val]) FROM [foo].[Widgets] AS [w] WHERE [w].[Val] = 1"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); var result = context.Widgets.Where(w => w.Val == 1).Select(w => MyContext9214.AddTwo(w.Val)).Single(); Assert.Equal(3, result); @@ -2593,11 +2593,11 @@ public async Task Include_with_order_by_on_interface_key() FROM [Parents] AS [p] LEFT JOIN [Children] AS [c] ON [p].[Id] = [c].[Parent10635Id] ORDER BY [p].[Id], [c].[Id]"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); var query = context.Parents.OrderBy(p => p.Id).Select(p => p.Children.ToList()).ToList(); AssertSql( @@ -4251,11 +4251,11 @@ public virtual async Task Derived_reference_is_skipped_when_base_type() FROM [Bases] AS [b] LEFT JOIN [Reference16233] AS [r] ON [b].[Id] = [r].[DerivedTypeId] ORDER BY [b].[Id]"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); var result = context.Bases.AsNoTracking().Include(p => ((MyContext16233.DerivedType16233)p).Reference).OrderBy(b => b.Id).ToList(); Assert.Equal(3, result.Count); @@ -4785,11 +4785,11 @@ FROM [EntitiesWithQueryFilterSelfReference] AS [e] WHERE EXISTS ( SELECT 1 FROM [EntitiesWithQueryFilterSelfReference] AS [e0]) AND (([e].[Name] <> N'Foo') OR [e].[Name] IS NULL)"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); var query = context.EntitiesReferencingEntityWithQueryFilterSelfReference.Where(e => e.Name != "Foo"); var result = query.ToList(); @@ -5036,12 +5036,12 @@ public virtual async Task Implicit_cast_6864() @"SELECT [f].[Id], [f].[String] FROM [Foos] AS [f] WHERE [f].[String] = N'1337'"); - ClearLog(); } //Access_property_of_closure using (var context = contextFactory.CreateContext()) { + ClearLog(); // Verify no client eval var bar = new MyContext6864.Bar6864(1337); var result = context.Foos.Where(f => f.String == bar.Value).ToList(); @@ -5054,12 +5054,12 @@ FROM [Foos] AS [f] SELECT [f].[Id], [f].[String] FROM [Foos] AS [f] WHERE [f].[String] = @__bar_Value_0"); - ClearLog(); } //Implicitly_cast_closure using (var context = contextFactory.CreateContext()) { + ClearLog(); // Verify no client eval var bar = new MyContext6864.Bar6864(1337); var result = context.Foos.Where(f => f.String == bar.ToString()).ToList(); @@ -5072,12 +5072,12 @@ FROM [Foos] AS [f] SELECT [f].[Id], [f].[String] FROM [Foos] AS [f] WHERE [f].[String] = @__ToString_0"); - ClearLog(); } //Implicitly_cast_closure using (var context = contextFactory.CreateContext()) { + ClearLog(); // Verify no client eval var bar = new MyContext6864.Bar6864(1337); var result = context.Foos.Where(f => f.String == bar).ToList(); @@ -5090,12 +5090,12 @@ FROM [Foos] AS [f] SELECT [f].[Id], [f].[String] FROM [Foos] AS [f] WHERE [f].[String] = @__p_0"); - ClearLog(); } // Implicitly_cast_return_value using (var context = contextFactory.CreateContext()) { + ClearLog(); // Verify no client eval var result = context.Foos.Where(f => f.String == new MyContext6864.Bar6864(1337).Clone()).ToList(); @@ -5265,11 +5265,11 @@ public virtual async Task Return_type_of_singular_operator_is_preserved() @"SELECT TOP(1) [p].[Name], [p].[Age] FROM [Persons] AS [p] WHERE [p].[Age] >= 21"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); var personsToFind = await context.Persons.Where(p => p.Age >= 21) .Select(p => new MyContext17644.PersonDetailView17644 { Name = p.Name, Age = p.Age }) .FirstOrDefaultAsync(); @@ -5278,11 +5278,11 @@ FROM [Persons] AS [p] @"SELECT TOP(1) [p].[Name], [p].[Age] FROM [Persons] AS [p] WHERE [p].[Age] >= 21"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); var personsToFind = await context.Persons.Where(p => p.Age >= 21) .Select(p => new MyContext17644.PersonDetailView17644 { Name = p.Name, Age = p.Age }) .SingleAsync(); @@ -5291,11 +5291,11 @@ FROM [Persons] AS [p] @"SELECT TOP(2) [p].[Name], [p].[Age] FROM [Persons] AS [p] WHERE [p].[Age] >= 21"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); var personsToFind = await context.Persons.Where(p => p.Age >= 21) .Select(p => new MyContext17644.PersonDetailView17644 { Name = p.Name, Age = p.Age }) .SingleOrDefaultAsync(); @@ -5304,11 +5304,11 @@ FROM [Persons] AS [p] @"SELECT TOP(2) [p].[Name], [p].[Age] FROM [Persons] AS [p] WHERE [p].[Age] >= 21"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); var personsToFind = await context.Persons.Where(p => p.Age >= 21) .OrderBy(p => p.Id) .Select(p => new MyContext17644.PersonDetailView17644 { Name = p.Name, Age = p.Age }) @@ -5319,11 +5319,11 @@ FROM [Persons] AS [p] FROM [Persons] AS [p] WHERE [p].[Age] >= 21 ORDER BY [p].[Id] DESC"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); var personsToFind = await context.Persons.Where(p => p.Age >= 21) .OrderBy(p => p.Id) .Select(p => new MyContext17644.PersonDetailView17644 { Name = p.Name, Age = p.Age }) @@ -5661,11 +5661,11 @@ FROM [CompetitionSeasons] AS [c1] WHERE ([c1].[StartDate] <= [a].[DateTime]) AND ([a].[DateTime] < [c1].[EndDate]))) AND ([a0].[Id] = [a1].[ActivityTypeId]) ) AS [t] ORDER BY [a].[Id], [a0].[Id], [t].[Id], [t].[Id0]"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); var users = context.Activities .Select( a => new @@ -5791,7 +5791,7 @@ public virtual async Task Max_in_multi_level_nested_subquery() .SingleAsync(); AssertSql( - @"SELECT [t0].[Id], [t1].[Id], [t1].[Id0] AS [Id], [t1].[Id1] AS [Id], [t1].[IsPastTradeDeadline] + @"SELECT [t0].[Id], [t1].[Id], [t1].[Id0], [t1].[Id1], [t1].[IsPastTradeDeadline] FROM ( SELECT TOP(2) [t].[Id] FROM [Trades] AS [t] @@ -6082,12 +6082,12 @@ public async Task Casts_are_removed_from_expression_tree_when_redundant() SELECT TOP(1) [m].[Id], [m].[Name], [m].[NavigationEntityId] FROM [MockEntities] AS [m] WHERE [m].[Id] = @__id_0"); - ClearLog(); } // object using (var context = contextFactory.CreateContext()) { + ClearLog(); var queryBase = (IQueryable)context.MockEntities; var query = queryBase.Cast().Count(); @@ -6096,12 +6096,12 @@ FROM [MockEntities] AS [m] AssertSql( @"SELECT COUNT(*) FROM [MockEntities] AS [m]"); - ClearLog(); } // non_implemented_interface using (var context = contextFactory.CreateContext()) { + ClearLog(); var queryBase = (IQueryable)context.MockEntities; var id = 1; @@ -6299,11 +6299,11 @@ SELECT COUNT(*) FROM [Customers] AS [c0] LEFT JOIN [CustomerMemberships] AS [c1] ON [c0].[Id] = [c1].[CustomerId] WHERE [c1].[Id] IS NOT NULL AND ([c0].[Id] = [c].[CustomerId])) > 0"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); var query = context.Set().ToList(); Assert.Collection( @@ -6450,11 +6450,11 @@ public async Task Interface_casting_though_generic_method() SELECT [e].[Id] FROM [Entities] AS [e] WHERE [e].[Id] = @__id_0"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); var originalQuery = context.Entities.Select(a => new IssueContext20097.MyModel20097 { Id = a.Id }); var query = originalQuery.Where(a => a.Id == 1).ToList(); @@ -6464,11 +6464,11 @@ FROM [Entities] AS [e] @"SELECT [e].[Id] FROM [Entities] AS [e] WHERE [e].[Id] = CAST(1 AS bigint)"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); var originalQuery = context.Entities.Select(a => new IssueContext20097.MyModel20097 { Id = a.Id }); var query = originalQuery.Where(a => ((IssueContext20097.IHaveId20097)a).Id == 1).ToList(); @@ -6478,11 +6478,11 @@ FROM [Entities] AS [e] @"SELECT [e].[Id] FROM [Entities] AS [e] WHERE [e].[Id] = CAST(1 AS bigint)"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); var originalQuery = context.Entities.Select(a => new IssueContext20097.MyModel20097 { Id = a.Id }); var query = originalQuery.Where(a => (a as IssueContext20097.IHaveId20097).Id == 1).ToList(); @@ -6492,11 +6492,11 @@ FROM [Entities] AS [e] @"SELECT [e].[Id] FROM [Entities] AS [e] WHERE [e].[Id] = CAST(1 AS bigint)"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); var originalQuery = context.Entities.Select(a => new IssueContext20097.MyModel20097 { Id = a.Id }); var query = originalQuery.Where(a => ((IssueContext20097.IHaveId20097)a).Id == 1).ToList(); Assert.Single(query); @@ -6505,7 +6505,6 @@ FROM [Entities] AS [e] @"SELECT [e].[Id] FROM [Entities] AS [e] WHERE [e].[Id] = CAST(1 AS bigint)"); - ClearLog(); } } @@ -6630,11 +6629,11 @@ FROM [Parents] AS [p] LEFT JOIN [Child21355] AS [c] ON [p].[Id] = [c].[ParentId] ORDER BY [p].[Id], [c].[Id]" }); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); var result = context.Parents.Include(p => p.Children1).AsSplitQuery().ToList(); AssertSql( @@ -6649,11 +6648,11 @@ FROM [Parents] AS [p] INNER JOIN [Child21355] AS [c] ON [p].[Id] = [c].[ParentId] ORDER BY [p].[Id]" }); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); context.Parents.Include(p => p.Children1).Include(p => p.Children2).ToList(); AssertSql( @@ -6690,11 +6689,11 @@ FROM [Parents] AS [p] INNER JOIN [Child21355] AS [c] ON [p].[Id] = [c].[ParentId] ORDER BY [p].[Id]" }); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); var result = context.Parents.Include(p => p.Children1).AsSingleQuery().ToList(); AssertSql( @@ -6705,11 +6704,11 @@ FROM [Parents] AS [p] LEFT JOIN [Child21355] AS [c] ON [p].[Id] = [c].[ParentId] ORDER BY [p].[Id], [c].[Id]" }); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); context.Parents.Include(p => p.Children1).Include(p => p.Children2).ToList(); AssertSql( @@ -6897,7 +6896,7 @@ public virtual async Task Can_auto_include_navigation_from_model() Assert.Single(result.SkipOtherSide); AssertSql( - @"SELECT [p].[Id], [p].[OwnedReference_Id], [r].[Id], [r].[ParentId], [c].[Id], [c].[ParentId], [t].[Id], [t].[ParentId], [t].[OtherSideId] + @"SELECT [p].[Id], [r].[Id], [c].[Id], [c].[ParentId], [p].[OwnedReference_Id], [r].[ParentId], [t].[Id], [t].[ParentId], [t].[OtherSideId] FROM [Parents] AS [p] LEFT JOIN [Reference21540] AS [r] ON [p].[Id] = [r].[ParentId] LEFT JOIN [Collection21540] AS [c] ON [p].[Id] = [c].[ParentId] @@ -6907,11 +6906,11 @@ FROM [JoinEntity21540] AS [j] INNER JOIN [OtherSide21540] AS [o] ON [j].[OtherSideId] = [o].[Id] ) AS [t] ON [p].[Id] = [t].[ParentId] ORDER BY [p].[Id], [r].[Id], [c].[Id], [t].[ParentId], [t].[OtherSideId], [t].[Id]"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); var query = context.Parents.AsNoTracking().IgnoreAutoIncludes().ToList(); var result = Assert.Single(query); @@ -8138,11 +8137,11 @@ FROM [PrincipalOneToOne] AS [p] @"SELECT [d].[Id], [d].[PrincipalId], [p].[Id] FROM [DependentOneToOne] AS [d] INNER JOIN [PrincipalOneToOne] AS [p] ON [d].[PrincipalId] = [p].[Id]"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); var principals = context.Set().ToList(); Assert.Single(principals); Assert.NotNull(principals[0].Dependents); @@ -8165,11 +8164,11 @@ FROM [DependentOneToMany] AS [d] INNER JOIN [PrincipalOneToMany] AS [p] ON [d].[PrincipalId] = [p].[Id] LEFT JOIN [DependentOneToMany] AS [d0] ON [p].[Id] = [d0].[PrincipalId] ORDER BY [d].[Id], [p].[Id], [d0].[Id]"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); Assert.Equal( CoreStrings.AutoIncludeNavigationCycle("'PrincipalManyToMany.Dependents', 'DependentManyToMany.Principals'"), Assert.Throws(() => context.Set().ToList()).Message); @@ -8187,11 +8186,11 @@ FROM [DependentOneToMany] AS [d] // @"SELECT [d].[Id] FROM [DependentManyToMany] AS [d]"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); Assert.Equal( CoreStrings.AutoIncludeNavigationCycle("'CycleA.Bs', 'CycleB.C', 'CycleC.As'"), Assert.Throws(() => context.Set().ToList()).Message); @@ -8407,11 +8406,11 @@ FROM [Posts] AS [p] WHERE [p].[Name] LIKE N'%2%' ) AS [t] ON [b].[Id] = [t].[BlogId] ORDER BY [b].[Id], [t].[Id]"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); var result = context.Blogs.Select( e => new { @@ -8510,11 +8509,11 @@ ORDER BY [o].[Id] ) AS [t] INNER JOIN [Dependent23211] AS [d] ON [t].[Id] = [d].[Owner23211Id] ORDER BY [t].[Id]"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); var owner = context.Set().Include(e => e.Dependents).AsSplitQuery().OrderBy(e => e.Id).Single(); Assert.NotNull(owner.Dependents); Assert.Equal(2, owner.Dependents.Count); @@ -8796,11 +8795,11 @@ UNION ALL FROM [B] AS [b0] LEFT JOIN [A] AS [a0] ON [b0].[forkey] = [a0].[forkey] WHERE [a0].[Id] IS NULL"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); Expression> leftKeySelector = x => x.forkey; Expression> rightKeySelector = y => y.forkey; @@ -8846,11 +8845,11 @@ FROM [A] AS [a] FROM [B] AS [b0] LEFT JOIN [A] AS [a0] ON [b0].[forkey] = [a0].[forkey] WHERE [a0].[Id] IS NULL"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); Expression> leftKeySelector = x => x.forkey; Expression> rightKeySelector = y => y.forkey; @@ -8894,11 +8893,11 @@ FROM [A] AS [a] SELECT [a0].[Id], [a0].[a], [a0].[a1], [a0].[forkey], [b0].[Id] AS [Id0], [b0].[b], [b0].[b1], [b0].[forkey] AS [forkey0] FROM [B] AS [b0] LEFT JOIN [A] AS [a0] ON [b0].[forkey] = [a0].[forkey]"); - ClearLog(); } using (var context = contextFactory.CreateContext()) { + ClearLog(); Expression> leftKeySelector = x => x.forkey; Expression> rightKeySelector = y => y.forkey; @@ -9627,27 +9626,27 @@ public virtual async Task Multiple_select_many_in_projection() // Verify the valid generated SQL AssertSql( - @"SELECT [t0].[c], [t0].[Id], [t1].[Rate], [t1].[UserRateText], [t1].[UserId], [t1].[Id], [t1].[Id0] + @"SELECT [t].[Id], [t1].[Rate], [t1].[UserRateText], [t1].[UserId], [t1].[Id], [t1].[Id0], [t].[c] FROM ( SELECT TOP(2) ( SELECT COUNT(*) FROM [Cars] AS [c] - INNER JOIN [Taxis] AS [t] ON [c].[Id] = [t].[CarId] - WHERE ([u].[Id] = [c].[EUserId]) AND (([t].[ReportText] <> N'') OR [t].[ReportText] IS NULL)) AS [c], [u].[Id] + INNER JOIN [Taxis] AS [t0] ON [c].[Id] = [t0].[CarId] + WHERE ([u].[Id] = [c].[EUserId]) AND (([t0].[ReportText] <> N'') OR [t0].[ReportText] IS NULL)) AS [c], [u].[Id] FROM [Users] AS [u] -) AS [t0] +) AS [t] OUTER APPLY ( SELECT [t2].[UserRate] AS [Rate], [t2].[UserTextRate] AS [UserRateText], [u0].[Id] AS [UserId], [t2].[Id], [t2].[Id0], [t2].[DateArrived] FROM ( SELECT TOP(12) [c0].[Id], [t3].[Id] AS [Id0], [t3].[DateArrived], [t3].[UserEUserId], [t3].[UserRate], [t3].[UserTextRate] FROM [Cars] AS [c0] INNER JOIN [Taxis] AS [t3] ON [c0].[Id] = [t3].[CarId] - WHERE [t0].[Id] = [c0].[EUserId] + WHERE [t].[Id] = [c0].[EUserId] ORDER BY [t3].[DateArrived] DESC ) AS [t2] LEFT JOIN [Users] AS [u0] ON [t2].[UserEUserId] = [u0].[Id] ) AS [t1] -ORDER BY [t0].[Id], [t1].[DateArrived] DESC, [t1].[Id], [t1].[Id0], [t1].[UserId]"); +ORDER BY [t].[Id], [t1].[DateArrived] DESC, [t1].[Id], [t1].[Id0], [t1].[UserId]"); } [ConditionalFact] @@ -9671,23 +9670,23 @@ public virtual async Task Single_select_many_in_projection_with_take() // Verify the valid generated SQL AssertSql( - @"SELECT [t].[Id], [t0].[Rate], [t0].[UserRateText], [t0].[UserId], [t0].[Id], [t0].[Id0] + @"SELECT [t].[Id], [t1].[Rate], [t1].[UserRateText], [t1].[UserId], [t1].[Id], [t1].[Id0] FROM ( SELECT TOP(2) [u].[Id] FROM [Users] AS [u] ) AS [t] OUTER APPLY ( - SELECT [t1].[UserRate] AS [Rate], [t1].[UserTextRate] AS [UserRateText], [u0].[Id] AS [UserId], [t1].[Id], [t1].[Id0], [t1].[DateArrived] + SELECT [t0].[UserRate] AS [Rate], [t0].[UserTextRate] AS [UserRateText], [u0].[Id] AS [UserId], [t0].[Id], [t0].[Id0], [t0].[DateArrived] FROM ( SELECT TOP(12) [c].[Id], [t2].[Id] AS [Id0], [t2].[DateArrived], [t2].[UserEUserId], [t2].[UserRate], [t2].[UserTextRate] FROM [Cars] AS [c] INNER JOIN [Taxis] AS [t2] ON [c].[Id] = [t2].[CarId] WHERE [t].[Id] = [c].[EUserId] ORDER BY [t2].[DateArrived] DESC - ) AS [t1] - LEFT JOIN [Users] AS [u0] ON [t1].[UserEUserId] = [u0].[Id] -) AS [t0] -ORDER BY [t].[Id], [t0].[DateArrived] DESC, [t0].[Id], [t0].[Id0], [t0].[UserId]"); + ) AS [t0] + LEFT JOIN [Users] AS [u0] ON [t0].[UserEUserId] = [u0].[Id] +) AS [t1] +ORDER BY [t].[Id], [t1].[DateArrived] DESC, [t1].[Id], [t1].[Id0], [t1].[UserId]"); } private class EUser diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs index 9c397182074..95494b14802 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs @@ -2307,9 +2307,9 @@ public override void Include_on_GroupJoin_SelectMany_DefaultIfEmpty_with_coalesc // Issue#16897 AssertSql( - @"SELECT [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOfBirthName], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank], [t].[Discriminator], [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], CASE + @"SELECT [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOfBirthName], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank], [t].[Discriminator], [g].[Nickname], [g].[SquadId], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], CASE WHEN [o].[Nickname] IS NOT NULL THEN N'Officer' -END AS [Discriminator], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] +END AS [Discriminator] FROM [Gears] AS [g] LEFT JOIN [Officers] AS [o] ON ([g].[Nickname] = [o].[Nickname]) AND ([g].[SquadId] = [o].[SquadId]) LEFT JOIN ( @@ -2329,9 +2329,9 @@ public override async Task Include_on_GroupJoin_SelectMany_DefaultIfEmpty_with_c // Issue#16897 AssertSql( - @"SELECT [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOfBirthName], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank], [t].[Discriminator], [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], CASE + @"SELECT [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOfBirthName], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank], [t].[Discriminator], [g].[Nickname], [g].[SquadId], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], CASE WHEN [o].[Nickname] IS NOT NULL THEN N'Officer' -END AS [Discriminator], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId], [w0].[Id], [w0].[AmmunitionType], [w0].[IsAutomatic], [w0].[Name], [w0].[OwnerFullName], [w0].[SynergyWithId] +END AS [Discriminator], [w0].[Id], [w0].[AmmunitionType], [w0].[IsAutomatic], [w0].[Name], [w0].[OwnerFullName], [w0].[SynergyWithId] FROM [Gears] AS [g] LEFT JOIN [Officers] AS [o] ON ([g].[Nickname] = [o].[Nickname]) AND ([g].[SquadId] = [o].[SquadId]) LEFT JOIN ( @@ -2397,9 +2397,9 @@ public override async Task Include_on_GroupJoin_SelectMany_DefaultIfEmpty_with_i // Issue#16897 AssertSql( - @"SELECT [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOfBirthName], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank], [t].[Discriminator], [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], CASE + @"SELECT [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOfBirthName], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank], [t].[Discriminator], [g].[Nickname], [g].[SquadId], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], CASE WHEN [o].[Nickname] IS NOT NULL THEN N'Officer' -END AS [Discriminator], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId], [w0].[Id], [w0].[AmmunitionType], [w0].[IsAutomatic], [w0].[Name], [w0].[OwnerFullName], [w0].[SynergyWithId] +END AS [Discriminator], [w0].[Id], [w0].[AmmunitionType], [w0].[IsAutomatic], [w0].[Name], [w0].[OwnerFullName], [w0].[SynergyWithId] FROM [Gears] AS [g] LEFT JOIN [Officers] AS [o] ON ([g].[Nickname] = [o].[Nickname]) AND ([g].[SquadId] = [o].[SquadId]) LEFT JOIN ( @@ -5164,7 +5164,7 @@ public override async Task Correlated_collections_from_left_join_with_additional await base.Correlated_collections_from_left_join_with_additional_elements_projected_of_that_join(async); AssertSql( - @"SELECT [w].[Id], [t].[Nickname], [t].[SquadId], [s].[Id], [t0].[Rank], [t0].[Nickname], [t0].[SquadId], [t0].[Id], [t0].[AmmunitionType], [t0].[IsAutomatic], [t0].[Name], [t0].[OwnerFullName], [t0].[SynergyWithId] + @"SELECT [w].[Id], [t].[Nickname], [t].[SquadId], [s].[Id], [t0].[Nickname], [t0].[SquadId], [t0].[Id], [t0].[AmmunitionType], [t0].[IsAutomatic], [t0].[Name], [t0].[OwnerFullName], [t0].[SynergyWithId], [t0].[Rank] FROM [Weapons] AS [w] LEFT JOIN ( SELECT [g].[Nickname], [g].[SquadId], [g].[FullName] @@ -5172,7 +5172,7 @@ FROM [Gears] AS [g] ) AS [t] ON [w].[OwnerFullName] = [t].[FullName] LEFT JOIN [Squads] AS [s] ON [t].[SquadId] = [s].[Id] LEFT JOIN ( - SELECT [g0].[Rank], [g0].[Nickname], [g0].[SquadId], [t1].[Id], [t1].[AmmunitionType], [t1].[IsAutomatic], [t1].[Name], [t1].[OwnerFullName], [t1].[SynergyWithId], [g0].[FullName] + SELECT [g0].[Nickname], [g0].[SquadId], [t1].[Id], [t1].[AmmunitionType], [t1].[IsAutomatic], [t1].[Name], [t1].[OwnerFullName], [t1].[SynergyWithId], [g0].[Rank], [g0].[FullName] FROM [Gears] AS [g0] LEFT JOIN ( SELECT [w0].[Id], [w0].[AmmunitionType], [w0].[IsAutomatic], [w0].[Name], [w0].[OwnerFullName], [w0].[SynergyWithId] @@ -5387,7 +5387,7 @@ public override async Task Include_on_derived_type_with_order_by_and_paging(bool AssertSql( @"@__p_0='10' -SELECT [t1].[Name], [t1].[LocustHordeId], [t1].[ThreatLevel], [t1].[ThreatLevelByte], [t1].[ThreatLevelNullableByte], [t1].[DefeatedByNickname], [t1].[DefeatedBySquadId], [t1].[HighCommandId], [t1].[Discriminator], [t1].[Nickname], [t1].[SquadId], [t1].[AssignedCityName], [t1].[CityOfBirthName], [t1].[FullName], [t1].[HasSoulPatch], [t1].[LeaderNickname], [t1].[LeaderSquadId], [t1].[Rank], [t1].[Discriminator0], [t1].[Id], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] +SELECT [t1].[Name], [t1].[LocustHordeId], [t1].[ThreatLevel], [t1].[ThreatLevelByte], [t1].[ThreatLevelNullableByte], [t1].[DefeatedByNickname], [t1].[DefeatedBySquadId], [t1].[HighCommandId], [t1].[Discriminator], [t1].[Nickname], [t1].[SquadId], [t1].[AssignedCityName], [t1].[CityOfBirthName], [t1].[FullName], [t1].[HasSoulPatch], [t1].[LeaderNickname], [t1].[LeaderSquadId], [t1].[Rank], [t1].[Discriminator0] AS [Discriminator], [t1].[Id], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] FROM ( SELECT TOP(@__p_0) [l].[Name], [l].[LocustHordeId], [l].[ThreatLevel], [l].[ThreatLevelByte], [l].[ThreatLevelNullableByte], [l0].[DefeatedByNickname], [l0].[DefeatedBySquadId], [l0].[HighCommandId], CASE WHEN [l0].[Name] IS NOT NULL THEN N'LocustCommander' @@ -8548,7 +8548,7 @@ public override async Task Correlated_collection_take(bool async) await base.Correlated_collection_take(async); AssertSql( - @"SELECT [g].[Nickname], [c].[Name], [c].[Location], [c].[Nation], [g].[SquadId], [t0].[Id], [t0].[AmmunitionType], [t0].[IsAutomatic], [t0].[Name], [t0].[OwnerFullName], [t0].[SynergyWithId] + @"SELECT [g].[Nickname], [g].[SquadId], [c].[Name], [t0].[Id], [t0].[AmmunitionType], [t0].[IsAutomatic], [t0].[Name], [t0].[OwnerFullName], [t0].[SynergyWithId], [c].[Location], [c].[Nation] FROM [Gears] AS [g] INNER JOIN [Cities] AS [c] ON [g].[CityOfBirthName] = [c].[Name] LEFT JOIN ( diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TPTManyToManyNoTrackingQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TPTManyToManyNoTrackingQuerySqlServerTest.cs index 5f7a29c7476..17865f22cdd 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TPTManyToManyNoTrackingQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TPTManyToManyNoTrackingQuerySqlServerTest.cs @@ -681,7 +681,7 @@ public override async Task Include_skip_navigation_and_reference(bool async) await base.Include_skip_navigation_and_reference(async); AssertSql( - @"SELECT [e].[Id], [e].[CollectionInverseId], [e].[ExtraId], [e].[Name], [e].[ReferenceInverseId], [e0].[Id], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId], [t].[Id], [t].[Name], [t].[EntityOneId], [t].[EntityTwoId] + @"SELECT [e].[Id], [e].[CollectionInverseId], [e].[ExtraId], [e].[Name], [e].[ReferenceInverseId], [e0].[Id], [t].[Id], [t].[Name], [t].[EntityOneId], [t].[EntityTwoId], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId] FROM [EntityTwos] AS [e] LEFT JOIN [EntityThrees] AS [e0] ON [e].[Id] = [e0].[ReferenceInverseId] LEFT JOIN ( diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TPTManyToManyQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TPTManyToManyQuerySqlServerTest.cs index dd664fc1302..fd8eef85fb9 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TPTManyToManyQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TPTManyToManyQuerySqlServerTest.cs @@ -680,7 +680,7 @@ public override async Task Include_skip_navigation_and_reference(bool async) await base.Include_skip_navigation_and_reference(async); AssertSql( - @"SELECT [e].[Id], [e].[CollectionInverseId], [e].[ExtraId], [e].[Name], [e].[ReferenceInverseId], [e0].[Id], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId], [t].[EntityOneId], [t].[EntityTwoId], [t].[Id], [t].[Name] + @"SELECT [e].[Id], [e].[CollectionInverseId], [e].[ExtraId], [e].[Name], [e].[ReferenceInverseId], [e0].[Id], [t].[EntityOneId], [t].[EntityTwoId], [t].[Id], [t].[Name], [e0].[CollectionInverseId], [e0].[Name], [e0].[ReferenceInverseId] FROM [EntityTwos] AS [e] LEFT JOIN [EntityThrees] AS [e0] ON [e].[Id] = [e0].[ReferenceInverseId] LEFT JOIN ( diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TPTRelationshipsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TPTRelationshipsQuerySqlServerTest.cs index 4213a9b6c97..7fd0e0e89ad 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TPTRelationshipsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TPTRelationshipsQuerySqlServerTest.cs @@ -23,7 +23,7 @@ public override void Changes_in_derived_related_entities_are_detected() base.Changes_in_derived_related_entities_are_detected(); AssertSql( - @"SELECT [t].[Id], [t].[Name], [t].[BaseId], [t].[Discriminator], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id0], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [t0].[Id], [t0].[BaseParentId], [t0].[Name], [t0].[DerivedProperty], [t0].[Discriminator] + @"SELECT [t].[Id], [t].[Name], [t].[BaseId], [t].[Discriminator], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [t].[Id0], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [t0].[Id], [t0].[BaseParentId], [t0].[Name], [t0].[DerivedProperty], [t0].[Discriminator] FROM ( SELECT TOP(2) [b].[Id], [b].[Name], [d].[BaseId], CASE WHEN [d].[Id] IS NOT NULL THEN N'DerivedInheritanceRelationshipEntity' @@ -51,7 +51,7 @@ public override async Task Include_collection_without_inheritance(bool async) AssertSql( @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE WHEN [d].[Id] IS NOT NULL THEN N'DerivedInheritanceRelationshipEntity' -END AS [Discriminator], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [c].[Id], [c].[Name], [c].[ParentId] +END AS [Discriminator], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [c].[Id], [c].[Name], [c].[ParentId] FROM [BaseEntities] AS [b] LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] @@ -65,7 +65,7 @@ public override async Task Include_collection_without_inheritance_reverse(bool a await base.Include_collection_without_inheritance_reverse(async); AssertSql( - @"SELECT [c].[Id], [c].[Name], [c].[ParentId], [t].[Id], [t].[Name], [t].[BaseId], [t].[Discriminator], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name] + @"SELECT [c].[Id], [c].[Name], [c].[ParentId], [t].[Id], [t].[Name], [t].[BaseId], [t].[Discriminator], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name] FROM [CollectionsOnBase] AS [c] LEFT JOIN ( SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE @@ -86,7 +86,7 @@ public override async Task Include_collection_without_inheritance_with_filter(bo AssertSql( @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE WHEN [d].[Id] IS NOT NULL THEN N'DerivedInheritanceRelationshipEntity' -END AS [Discriminator], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [c].[Id], [c].[Name], [c].[ParentId] +END AS [Discriminator], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [c].[Id], [c].[Name], [c].[ParentId] FROM [BaseEntities] AS [b] LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] @@ -101,7 +101,7 @@ public override async Task Include_collection_without_inheritance_with_filter_re await base.Include_collection_without_inheritance_with_filter_reverse(async); AssertSql( - @"SELECT [c].[Id], [c].[Name], [c].[ParentId], [t].[Id], [t].[Name], [t].[BaseId], [t].[Discriminator], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name] + @"SELECT [c].[Id], [c].[Name], [c].[ParentId], [t].[Id], [t].[Name], [t].[BaseId], [t].[Discriminator], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name] FROM [CollectionsOnBase] AS [c] LEFT JOIN ( SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE @@ -123,7 +123,7 @@ public override async Task Include_collection_with_inheritance(bool async) AssertSql( @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE WHEN [d].[Id] IS NOT NULL THEN N'DerivedInheritanceRelationshipEntity' -END AS [Discriminator], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[DerivedProperty], [t].[Discriminator] +END AS [Discriminator], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[DerivedProperty], [t].[Discriminator] FROM [BaseEntities] AS [b] LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] @@ -143,7 +143,7 @@ public override async Task Include_collection_with_inheritance_on_derived1(bool await base.Include_collection_with_inheritance_on_derived1(async); AssertSql( - @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[DerivedProperty], [t].[Discriminator] + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[DerivedProperty], [t].[Discriminator] FROM [BaseEntities] AS [b] INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] @@ -163,7 +163,7 @@ public override async Task Include_collection_with_inheritance_on_derived2(bool await base.Include_collection_with_inheritance_on_derived2(async); AssertSql( - @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [t].[Id], [t].[Name], [t].[ParentId], [t].[DerivedInheritanceRelationshipEntityId], [t].[Discriminator] + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[Name], [t].[ParentId], [t].[DerivedInheritanceRelationshipEntityId], [t].[Discriminator] FROM [BaseEntities] AS [b] INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] @@ -183,7 +183,7 @@ public override async Task Include_collection_with_inheritance_on_derived3(bool await base.Include_collection_with_inheritance_on_derived3(async); AssertSql( - @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [t].[Id], [t].[Name], [t].[ParentId], [t].[DerivedInheritanceRelationshipEntityId] + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[Name], [t].[ParentId], [t].[DerivedInheritanceRelationshipEntityId] FROM [BaseEntities] AS [b] INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] @@ -203,7 +203,7 @@ public override async Task Include_collection_with_inheritance_on_derived_revers AssertSql( @"SELECT [b].[Id], [b].[Name], [b].[ParentId], [d].[DerivedInheritanceRelationshipEntityId], CASE WHEN [d].[Id] IS NOT NULL THEN N'DerivedCollectionOnDerived' -END AS [Discriminator], [t].[Id], [t].[Name], [t].[BaseId], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +END AS [Discriminator], [t].[Id], [t].[Name], [t].[BaseId], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name] FROM [BaseCollectionsOnDerived] AS [b] LEFT JOIN [DerivedCollectionsOnDerived] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN ( @@ -223,7 +223,7 @@ public override async Task Include_collection_with_inheritance_reverse(bool asyn AssertSql( @"SELECT [b].[Id], [b].[BaseParentId], [b].[Name], [d].[DerivedProperty], CASE WHEN [d].[Id] IS NOT NULL THEN N'DerivedCollectionOnBase' -END AS [Discriminator], [t].[Id], [t].[Name], [t].[BaseId], [t].[Discriminator], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +END AS [Discriminator], [t].[Id], [t].[Name], [t].[BaseId], [t].[Discriminator], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name] FROM [BaseCollectionsOnBase] AS [b] LEFT JOIN [DerivedCollectionsOnBase] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN ( @@ -245,7 +245,7 @@ public override async Task Include_collection_with_inheritance_with_filter(bool AssertSql( @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE WHEN [d].[Id] IS NOT NULL THEN N'DerivedInheritanceRelationshipEntity' -END AS [Discriminator], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[DerivedProperty], [t].[Discriminator] +END AS [Discriminator], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[DerivedProperty], [t].[Discriminator] FROM [BaseEntities] AS [b] LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] @@ -268,7 +268,7 @@ public override async Task Include_collection_with_inheritance_with_filter_rever AssertSql( @"SELECT [b].[Id], [b].[BaseParentId], [b].[Name], [d].[DerivedProperty], CASE WHEN [d].[Id] IS NOT NULL THEN N'DerivedCollectionOnBase' -END AS [Discriminator], [t].[Id], [t].[Name], [t].[BaseId], [t].[Discriminator], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +END AS [Discriminator], [t].[Id], [t].[Name], [t].[BaseId], [t].[Discriminator], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name] FROM [BaseCollectionsOnBase] AS [b] LEFT JOIN [DerivedCollectionsOnBase] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN ( @@ -291,7 +291,7 @@ public override async Task Include_reference_without_inheritance(bool async) AssertSql( @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE WHEN [d].[Id] IS NOT NULL THEN N'DerivedInheritanceRelationshipEntity' -END AS [Discriminator], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [r].[Id], [r].[Name], [r].[ParentId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name] +END AS [Discriminator], [r].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [r].[Name], [r].[ParentId] FROM [BaseEntities] AS [b] LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN [ReferencesOnBase] AS [r] ON [b].[Id] = [r].[ParentId] @@ -305,7 +305,7 @@ public override async Task Include_reference_without_inheritance_on_derived1(boo await base.Include_reference_without_inheritance_on_derived1(async); AssertSql( - @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [r].[Id], [r].[Name], [r].[ParentId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name] + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [r].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [r].[Name], [r].[ParentId] FROM [BaseEntities] AS [b] INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN [ReferencesOnBase] AS [r] ON [b].[Id] = [r].[ParentId] @@ -319,7 +319,7 @@ public override async Task Include_reference_without_inheritance_on_derived2(boo await base.Include_reference_without_inheritance_on_derived2(async); AssertSql( - @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [r].[Id], [r].[Name], [r].[ParentId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name] + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [r].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [r].[Name], [r].[ParentId] FROM [BaseEntities] AS [b] INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN [ReferencesOnDerived] AS [r] ON [b].[Id] = [r].[ParentId] @@ -333,7 +333,7 @@ public override async Task Include_reference_without_inheritance_on_derived_reve await base.Include_reference_without_inheritance_on_derived_reverse(async); AssertSql( - @"SELECT [r].[Id], [r].[Name], [r].[ParentId], [t].[Id], [t].[Name], [t].[BaseId], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name] + @"SELECT [r].[Id], [r].[Name], [r].[ParentId], [t].[Id], [t].[Name], [t].[BaseId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name] FROM [ReferencesOnDerived] AS [r] LEFT JOIN ( SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[Id] AS [Id0], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id] AS [Id1], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name] @@ -350,7 +350,7 @@ public override async Task Include_reference_without_inheritance_reverse(bool as await base.Include_reference_without_inheritance_reverse(async); AssertSql( - @"SELECT [r].[Id], [r].[Name], [r].[ParentId], [t].[Id], [t].[Name], [t].[BaseId], [t].[Discriminator], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name] + @"SELECT [r].[Id], [r].[Name], [r].[ParentId], [t].[Id], [t].[Name], [t].[BaseId], [t].[Discriminator], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name] FROM [ReferencesOnBase] AS [r] LEFT JOIN ( SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE @@ -371,7 +371,7 @@ public override async Task Include_reference_without_inheritance_with_filter(boo AssertSql( @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE WHEN [d].[Id] IS NOT NULL THEN N'DerivedInheritanceRelationshipEntity' -END AS [Discriminator], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [r].[Id], [r].[Name], [r].[ParentId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name] +END AS [Discriminator], [r].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [r].[Name], [r].[ParentId] FROM [BaseEntities] AS [b] LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN [ReferencesOnBase] AS [r] ON [b].[Id] = [r].[ParentId] @@ -386,7 +386,7 @@ public override async Task Include_reference_without_inheritance_with_filter_rev await base.Include_reference_without_inheritance_with_filter_reverse(async); AssertSql( - @"SELECT [r].[Id], [r].[Name], [r].[ParentId], [t].[Id], [t].[Name], [t].[BaseId], [t].[Discriminator], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name] + @"SELECT [r].[Id], [r].[Name], [r].[ParentId], [t].[Id], [t].[Name], [t].[BaseId], [t].[Discriminator], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name] FROM [ReferencesOnBase] AS [r] LEFT JOIN ( SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE @@ -408,7 +408,7 @@ public override async Task Include_reference_with_inheritance(bool async) AssertSql( @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE WHEN [d].[Id] IS NOT NULL THEN N'DerivedInheritanceRelationshipEntity' -END AS [Discriminator], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[Discriminator], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +END AS [Discriminator], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[BaseParentId], [t].[Name], [t].[Discriminator] FROM [BaseEntities] AS [b] LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN ( @@ -428,7 +428,7 @@ public override async Task Include_reference_with_inheritance_on_derived1(bool a await base.Include_reference_with_inheritance_on_derived1(async); AssertSql( - @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[Discriminator], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[BaseParentId], [t].[Name], [t].[Discriminator] FROM [BaseEntities] AS [b] INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN ( @@ -448,7 +448,7 @@ public override async Task Include_reference_with_inheritance_on_derived2(bool a await base.Include_reference_with_inheritance_on_derived2(async); AssertSql( - @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[DerivedInheritanceRelationshipEntityId], [t].[Discriminator], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[BaseParentId], [t].[Name], [t].[DerivedInheritanceRelationshipEntityId], [t].[Discriminator] FROM [BaseEntities] AS [b] INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN ( @@ -468,7 +468,7 @@ public override async Task Include_reference_with_inheritance_on_derived4(bool a await base.Include_reference_with_inheritance_on_derived4(async); AssertSql( - @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[DerivedInheritanceRelationshipEntityId], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[BaseParentId], [t].[Name], [t].[DerivedInheritanceRelationshipEntityId] FROM [BaseEntities] AS [b] INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN ( @@ -488,7 +488,7 @@ public override async Task Include_reference_with_inheritance_on_derived_reverse AssertSql( @"SELECT [b].[Id], [b].[BaseParentId], [b].[Name], [d].[DerivedInheritanceRelationshipEntityId], CASE WHEN [d].[Id] IS NOT NULL THEN N'DerivedReferenceOnDerived' -END AS [Discriminator], [t].[Id], [t].[Name], [t].[BaseId], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +END AS [Discriminator], [t].[Id], [t].[Name], [t].[BaseId], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name] FROM [BaseReferencesOnDerived] AS [b] LEFT JOIN [DerivedReferencesOnDerived] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN ( @@ -506,7 +506,7 @@ public override async Task Include_reference_with_inheritance_on_derived_with_fi await base.Include_reference_with_inheritance_on_derived_with_filter1(async); AssertSql( - @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[Discriminator], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[BaseParentId], [t].[Name], [t].[Discriminator] FROM [BaseEntities] AS [b] INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN ( @@ -527,7 +527,7 @@ public override async Task Include_reference_with_inheritance_on_derived_with_fi await base.Include_reference_with_inheritance_on_derived_with_filter2(async); AssertSql( - @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[DerivedInheritanceRelationshipEntityId], [t].[Discriminator], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[BaseParentId], [t].[Name], [t].[DerivedInheritanceRelationshipEntityId], [t].[Discriminator] FROM [BaseEntities] AS [b] INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN ( @@ -548,7 +548,7 @@ public override async Task Include_reference_with_inheritance_on_derived_with_fi await base.Include_reference_with_inheritance_on_derived_with_filter4(async); AssertSql( - @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[DerivedInheritanceRelationshipEntityId], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[BaseParentId], [t].[Name], [t].[DerivedInheritanceRelationshipEntityId] FROM [BaseEntities] AS [b] INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN ( @@ -569,7 +569,7 @@ public override async Task Include_reference_with_inheritance_on_derived_with_fi AssertSql( @"SELECT [b].[Id], [b].[BaseParentId], [b].[Name], [d].[DerivedInheritanceRelationshipEntityId], CASE WHEN [d].[Id] IS NOT NULL THEN N'DerivedReferenceOnDerived' -END AS [Discriminator], [t].[Id], [t].[Name], [t].[BaseId], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +END AS [Discriminator], [t].[Id], [t].[Name], [t].[BaseId], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name] FROM [BaseReferencesOnDerived] AS [b] LEFT JOIN [DerivedReferencesOnDerived] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN ( @@ -590,7 +590,7 @@ public override async Task Include_reference_with_inheritance_reverse(bool async AssertSql( @"SELECT [b].[Id], [b].[BaseParentId], [b].[Name], CASE WHEN [d].[Id] IS NOT NULL THEN N'DerivedReferenceOnBase' -END AS [Discriminator], [t].[Id], [t].[Name], [t].[BaseId], [t].[Discriminator], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +END AS [Discriminator], [t].[Id], [t].[Name], [t].[BaseId], [t].[Discriminator], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name] FROM [BaseReferencesOnBase] AS [b] LEFT JOIN [DerivedReferencesOnBase] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN ( @@ -612,7 +612,7 @@ public override async Task Include_reference_with_inheritance_with_filter(bool a AssertSql( @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE WHEN [d].[Id] IS NOT NULL THEN N'DerivedInheritanceRelationshipEntity' -END AS [Discriminator], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[Discriminator], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +END AS [Discriminator], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[BaseParentId], [t].[Name], [t].[Discriminator] FROM [BaseEntities] AS [b] LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN ( @@ -635,7 +635,7 @@ public override async Task Include_reference_with_inheritance_with_filter_revers AssertSql( @"SELECT [b].[Id], [b].[BaseParentId], [b].[Name], CASE WHEN [d].[Id] IS NOT NULL THEN N'DerivedReferenceOnBase' -END AS [Discriminator], [t].[Id], [t].[Name], [t].[BaseId], [t].[Discriminator], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +END AS [Discriminator], [t].[Id], [t].[Name], [t].[BaseId], [t].[Discriminator], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name] FROM [BaseReferencesOnBase] AS [b] LEFT JOIN [DerivedReferencesOnBase] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN ( @@ -658,7 +658,7 @@ public override async Task Include_self_reference_with_inheritance(bool async) AssertSql( @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE WHEN [d].[Id] IS NOT NULL THEN N'DerivedInheritanceRelationshipEntity' -END AS [Discriminator], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[Name], [t].[BaseId], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [b2].[BaseInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [d2].[DerivedInheritanceRelationshipEntityId], [d2].[Id], [d2].[Name] +END AS [Discriminator], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Name], [t].[BaseId], [b2].[BaseInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [d2].[DerivedInheritanceRelationshipEntityId], [d2].[Id], [d2].[Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name] FROM [BaseEntities] AS [b] LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN ( @@ -678,7 +678,7 @@ public override async Task Include_self_reference_with_inheritance_reverse(bool await base.Include_self_reference_with_inheritance_reverse(async); AssertSql( - @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[Name], [t].[BaseId], [t].[Discriminator], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [b2].[BaseInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [d2].[DerivedInheritanceRelationshipEntityId], [d2].[Id], [d2].[Name] + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Name], [t].[BaseId], [t].[Discriminator], [b2].[BaseInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [d2].[DerivedInheritanceRelationshipEntityId], [d2].[Id], [d2].[Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name] FROM [BaseEntities] AS [b] INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN ( @@ -717,7 +717,7 @@ public override async Task Nested_include_with_inheritance_collection_collection AssertSql( @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE WHEN [d].[Id] IS NOT NULL THEN N'DerivedInheritanceRelationshipEntity' -END AS [Discriminator], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [t0].[Id], [t0].[BaseParentId], [t0].[Name], [t0].[DerivedProperty], [t0].[Discriminator], [t0].[Id0], [t0].[Name0], [t0].[ParentCollectionId], [t0].[ParentReferenceId], [t0].[Discriminator0] +END AS [Discriminator], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t0].[Id], [t0].[BaseParentId], [t0].[Name], [t0].[DerivedProperty], [t0].[Discriminator], [t0].[Id0], [t0].[Name0], [t0].[ParentCollectionId], [t0].[ParentReferenceId], [t0].[Discriminator0] FROM [BaseEntities] AS [b] LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] @@ -746,7 +746,7 @@ public override async Task Nested_include_with_inheritance_collection_collection AssertSql( @"SELECT [n].[Id], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId], CASE WHEN [n0].[Id] IS NOT NULL THEN N'NestedCollectionDerived' -END AS [Discriminator], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[DerivedProperty], [t].[Discriminator], [t0].[Id], [t0].[Name], [t0].[BaseId], [t0].[Discriminator], [t0].[Id0], [t0].[OwnedReferenceOnBase_Id], [t0].[OwnedReferenceOnBase_Name], [t0].[Id1], [t0].[OwnedReferenceOnDerived_Id], [t0].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +END AS [Discriminator], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[DerivedProperty], [t].[Discriminator], [t0].[Id], [t0].[Name], [t0].[BaseId], [t0].[Discriminator], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [t0].[Id0], [t0].[OwnedReferenceOnBase_Id], [t0].[OwnedReferenceOnBase_Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [t0].[Id1], [t0].[OwnedReferenceOnDerived_Id], [t0].[OwnedReferenceOnDerived_Name] FROM [NestedCollections] AS [n] LEFT JOIN [NestedCollectionsDerived] AS [n0] ON [n].[Id] = [n0].[Id] LEFT JOIN ( @@ -775,7 +775,7 @@ public override async Task Nested_include_with_inheritance_collection_reference( AssertSql( @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE WHEN [d].[Id] IS NOT NULL THEN N'DerivedInheritanceRelationshipEntity' -END AS [Discriminator], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [t0].[Id], [t0].[BaseParentId], [t0].[Name], [t0].[DerivedProperty], [t0].[Discriminator], [t0].[Id0], [t0].[Name0], [t0].[ParentCollectionId], [t0].[ParentReferenceId], [t0].[Discriminator0] +END AS [Discriminator], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t0].[Id], [t0].[BaseParentId], [t0].[Name], [t0].[DerivedProperty], [t0].[Discriminator], [t0].[Id0], [t0].[Name0], [t0].[ParentCollectionId], [t0].[ParentReferenceId], [t0].[Discriminator0] FROM [BaseEntities] AS [b] LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] @@ -804,7 +804,7 @@ public override async Task Nested_include_with_inheritance_collection_reference_ AssertSql( @"SELECT [n].[Id], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId], CASE WHEN [n0].[Id] IS NOT NULL THEN N'NestedReferenceDerived' -END AS [Discriminator], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[DerivedProperty], [t].[Discriminator], [t0].[Id], [t0].[Name], [t0].[BaseId], [t0].[Discriminator], [t0].[Id0], [t0].[OwnedReferenceOnBase_Id], [t0].[OwnedReferenceOnBase_Name], [t0].[Id1], [t0].[OwnedReferenceOnDerived_Id], [t0].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +END AS [Discriminator], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[DerivedProperty], [t].[Discriminator], [t0].[Id], [t0].[Name], [t0].[BaseId], [t0].[Discriminator], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [t0].[Id0], [t0].[OwnedReferenceOnBase_Id], [t0].[OwnedReferenceOnBase_Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [t0].[Id1], [t0].[OwnedReferenceOnDerived_Id], [t0].[OwnedReferenceOnDerived_Name] FROM [NestedReferences] AS [n] LEFT JOIN [NestedReferencesDerived] AS [n0] ON [n].[Id] = [n0].[Id] LEFT JOIN ( @@ -833,7 +833,7 @@ public override async Task Nested_include_with_inheritance_reference_collection( AssertSql( @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE WHEN [d].[Id] IS NOT NULL THEN N'DerivedInheritanceRelationshipEntity' -END AS [Discriminator], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[Discriminator], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [t0].[Id], [t0].[Name], [t0].[ParentCollectionId], [t0].[ParentReferenceId], [t0].[Discriminator] +END AS [Discriminator], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[BaseParentId], [t].[Name], [t].[Discriminator], [t0].[Id], [t0].[Name], [t0].[ParentCollectionId], [t0].[ParentReferenceId], [t0].[Discriminator] FROM [BaseEntities] AS [b] LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN ( @@ -860,7 +860,7 @@ public override async Task Nested_include_with_inheritance_reference_collection_ await base.Nested_include_with_inheritance_reference_collection_on_base(async); AssertSql( - @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[Discriminator], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [t0].[Id], [t0].[Name], [t0].[ParentCollectionId], [t0].[ParentReferenceId], [t0].[Discriminator] + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[BaseParentId], [t].[Name], [t].[Discriminator], [t0].[Id], [t0].[Name], [t0].[ParentCollectionId], [t0].[ParentReferenceId], [t0].[Discriminator] FROM [BaseEntities] AS [b] INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN ( @@ -889,7 +889,7 @@ public override async Task Nested_include_with_inheritance_reference_collection_ AssertSql( @"SELECT [n].[Id], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId], CASE WHEN [n0].[Id] IS NOT NULL THEN N'NestedCollectionDerived' -END AS [Discriminator], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[Discriminator], [t0].[Id], [t0].[Name], [t0].[BaseId], [t0].[Discriminator], [t0].[Id0], [t0].[OwnedReferenceOnBase_Id], [t0].[OwnedReferenceOnBase_Name], [t0].[Id1], [t0].[OwnedReferenceOnDerived_Id], [t0].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +END AS [Discriminator], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[Discriminator], [t0].[Id], [t0].[Name], [t0].[BaseId], [t0].[Discriminator], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [t0].[Id0], [t0].[OwnedReferenceOnBase_Id], [t0].[OwnedReferenceOnBase_Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [t0].[Id1], [t0].[OwnedReferenceOnDerived_Id], [t0].[OwnedReferenceOnDerived_Name] FROM [NestedCollections] AS [n] LEFT JOIN [NestedCollectionsDerived] AS [n0] ON [n].[Id] = [n0].[Id] LEFT JOIN ( @@ -918,7 +918,7 @@ public override async Task Nested_include_with_inheritance_reference_reference(b AssertSql( @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE WHEN [d].[Id] IS NOT NULL THEN N'DerivedInheritanceRelationshipEntity' -END AS [Discriminator], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[Discriminator], [t0].[Id], [t0].[Name], [t0].[ParentCollectionId], [t0].[ParentReferenceId], [t0].[Discriminator], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +END AS [Discriminator], [t].[Id], [t0].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[BaseParentId], [t].[Name], [t].[Discriminator], [t0].[Name], [t0].[ParentCollectionId], [t0].[ParentReferenceId], [t0].[Discriminator] FROM [BaseEntities] AS [b] LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN ( @@ -945,7 +945,7 @@ public override async Task Nested_include_with_inheritance_reference_reference_o await base.Nested_include_with_inheritance_reference_reference_on_base(async); AssertSql( - @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[Discriminator], [t0].[Id], [t0].[Name], [t0].[ParentCollectionId], [t0].[ParentReferenceId], [t0].[Discriminator], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [t].[Id], [t0].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[BaseParentId], [t].[Name], [t].[Discriminator], [t0].[Name], [t0].[ParentCollectionId], [t0].[ParentReferenceId], [t0].[Discriminator] FROM [BaseEntities] AS [b] INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN ( @@ -974,7 +974,7 @@ public override async Task Nested_include_with_inheritance_reference_reference_r AssertSql( @"SELECT [n].[Id], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId], CASE WHEN [n0].[Id] IS NOT NULL THEN N'NestedReferenceDerived' -END AS [Discriminator], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[Discriminator], [t0].[Id], [t0].[Name], [t0].[BaseId], [t0].[Discriminator], [t0].[Id0], [t0].[OwnedReferenceOnBase_Id], [t0].[OwnedReferenceOnBase_Name], [t0].[Id1], [t0].[OwnedReferenceOnDerived_Id], [t0].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +END AS [Discriminator], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[Discriminator], [t0].[Id], [t0].[Name], [t0].[BaseId], [t0].[Discriminator], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [t0].[Id0], [t0].[OwnedReferenceOnBase_Id], [t0].[OwnedReferenceOnBase_Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [t0].[Id1], [t0].[OwnedReferenceOnDerived_Id], [t0].[OwnedReferenceOnDerived_Name] FROM [NestedReferences] AS [n] LEFT JOIN [NestedReferencesDerived] AS [n0] ON [n].[Id] = [n0].[Id] LEFT JOIN ( @@ -1445,7 +1445,7 @@ public override async Task Nested_include_with_inheritance_reference_collection_ AssertSql( @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE WHEN [d].[Id] IS NOT NULL THEN N'DerivedInheritanceRelationshipEntity' -END AS [Discriminator], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[Discriminator] +END AS [Discriminator], [t].[Id], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[BaseParentId], [t].[Name], [t].[Discriminator] FROM [BaseEntities] AS [b] LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN ( @@ -1496,7 +1496,7 @@ public override async Task Nested_include_with_inheritance_reference_collection_ await base.Nested_include_with_inheritance_reference_collection_on_base_split(async); AssertSql( - @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[Discriminator] + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [t].[Id], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[BaseParentId], [t].[Name], [t].[Discriminator] FROM [BaseEntities] AS [b] INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] LEFT JOIN ( diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsQuerySqliteTest.cs index 24297cdb512..0bc87082329 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsQuerySqliteTest.cs @@ -106,5 +106,23 @@ public override async Task Skip_Take_Select_collection_Skip_Take(bool async) SqliteStrings.ApplyNotSupported, (await Assert.ThrowsAsync( () => base.Skip_Take_Select_collection_Skip_Take(async))).Message); + + public override async Task Select_subquery_single_nested_subquery(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.Select_subquery_single_nested_subquery(async))).Message); + + public override async Task Select_subquery_single_nested_subquery2(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.Select_subquery_single_nested_subquery2(async))).Message); + + public override void Member_pushdown_chain_3_levels_deep_entity() + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (Assert.Throws( + () => base.Member_pushdown_chain_3_levels_deep_entity())).Message); } } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsSharedTypeQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsSharedTypeQuerySqliteTest.cs index a3755db71d9..847cdfa4df4 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsSharedTypeQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsSharedTypeQuerySqliteTest.cs @@ -96,5 +96,17 @@ public override async Task Skip_Take_Select_collection_Skip_Take(bool async) SqliteStrings.ApplyNotSupported, (await Assert.ThrowsAsync( () => base.Skip_Take_Select_collection_Skip_Take(async))).Message); + + public override async Task Select_subquery_single_nested_subquery(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.Select_subquery_single_nested_subquery(async))).Message); + + public override async Task Select_subquery_single_nested_subquery2(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.Select_subquery_single_nested_subquery2(async))).Message); } } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindIncludeNoTrackingQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindIncludeNoTrackingQuerySqliteTest.cs index ef2e2f5d2e2..c3259424e8a 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindIncludeNoTrackingQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindIncludeNoTrackingQuerySqliteTest.cs @@ -48,11 +48,15 @@ public override async Task Include_collection_with_outer_apply_with_filter_non_e () => base.Include_collection_with_outer_apply_with_filter_non_equality(async))).Message); public override async Task Include_collection_with_last_no_orderby(bool async) - { - Assert.Equal( + => Assert.Equal( RelationalStrings.LastUsedWithoutOrderBy(nameof(Enumerable.Last)), (await Assert.ThrowsAsync( () => base.Include_collection_with_last_no_orderby(async))).Message); - } + + public override async Task Include_in_let_followed_by_FirstOrDefault(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.Include_in_let_followed_by_FirstOrDefault(async))).Message); } } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindIncludeQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindIncludeQuerySqliteTest.cs index b5550f1b9dc..d22958f8a9e 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindIncludeQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindIncludeQuerySqliteTest.cs @@ -41,5 +41,11 @@ public override async Task Include_collection_with_outer_apply_with_filter_non_e SqliteStrings.ApplyNotSupported, (await Assert.ThrowsAsync( () => base.Include_collection_with_outer_apply_with_filter_non_equality(async))).Message); + + public override async Task Include_in_let_followed_by_FirstOrDefault(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.Include_in_let_followed_by_FirstOrDefault(async))).Message); } } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindSelectQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindSelectQuerySqliteTest.cs index 2847d12f919..34d1db97a3b 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindSelectQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindSelectQuerySqliteTest.cs @@ -259,6 +259,12 @@ public override async Task Take_on_correlated_collection_in_first(bool async) (await Assert.ThrowsAsync( () => base.Take_on_correlated_collection_in_first(async))).Message); + public override async Task Collection_include_over_result_of_single_non_scalar(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.Collection_include_over_result_of_single_non_scalar(async))).Message); + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); } diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindStringIncludeQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindStringIncludeQuerySqliteTest.cs index a643243a0b0..00798a23c99 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindStringIncludeQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/NorthwindStringIncludeQuerySqliteTest.cs @@ -42,11 +42,15 @@ public override async Task Include_collection_with_outer_apply_with_filter_non_e () => base.Include_collection_with_outer_apply_with_filter_non_equality(async))).Message); public override async Task Include_collection_with_last_no_orderby(bool async) - { - Assert.Equal( + => Assert.Equal( RelationalStrings.LastUsedWithoutOrderBy(nameof(Enumerable.Last)), (await Assert.ThrowsAsync( () => base.Include_collection_with_last_no_orderby(async))).Message); - } + + public override async Task Include_in_let_followed_by_FirstOrDefault(bool async) + => Assert.Equal( + SqliteStrings.ApplyNotSupported, + (await Assert.ThrowsAsync( + () => base.Include_in_let_followed_by_FirstOrDefault(async))).Message); } }