From d11f6077e5a6827d2099f4cd40e855e65ebd0b56 Mon Sep 17 00:00:00 2001 From: Smit Patel Date: Sat, 10 Aug 2019 00:00:27 -0700 Subject: [PATCH] Relational: Translate SelectMany SelectMany in linq look something like following (second clause is considered the collection selector) ```C# from c in cs from o in c.Orders select.... ``` Following are the translations of SelectMany Unrelated collection selector ```C# from c in cs from o in os ``` Generates CROSS JOIN Correlated collection selector with correlation being a predicate ```C# from c in cs from o in os.Where(o => o.CustomerID == c.CustomerID) ``` Such predicate can be lifted and used in generating a join. So this query generates JOIN. If collection selector ends with DefaultIfEmpty then it is LEFT JOIN. Correlated collection selector with correlation not a predicate ```C# from c in cs from o in os.Select(o => c.City) ``` Since we cannot generate a join predicate here, this translates to CROSS APPLY. If collection selector ends with DefaultIfEmpty then it is OUTER APPLY. - Add support for Cross Apply - Add Support for Outer Apply - Convert Cross Apply to Inner Join when possible - Convert Outer Apply to Left Join when possible - Add translation for DefaultIfEmpty - Add translation for both overloads of SelectMany - Handle DefaultIfEmpty & SelectMany without collectionSelector in Navigation Expansion - Ensure columns are in projection when generating join predicate from a correlated subquery Currently there are no tests for Cross/Outer Apply. Our earlier Cross Apply got converted to join. N+1 evaluation tests are disabled right now, which would generate Cross Apply. We never supported Outer Apply in past. Resolves #15711 Resolves #12567 Resolves #12572 Resolves #12872 Resolves #16330 Resolves #15081 Resolves #16989 Re-enable tests for #12449 --- ...yExpressionTranslatingExpressionVisitor.cs | 2 +- ...yableMethodTranslatingExpressionVisitor.cs | 14 +- .../Query/QuerySqlGenerator.cs | 16 + ...yableMethodTranslatingExpressionVisitor.cs | 95 +++- .../Query/SqlExpressionVisitor.cs | 8 + .../SqlExpressions/CrossApplyExpression.cs | 41 ++ .../SqlExpressions/OuterApplyExpression.cs | 40 ++ .../Query/SqlExpressions/SelectExpression.cs | 212 +++++++- ...rchConditionConvertingExpressionVisitor.cs | 20 + .../NavigationExpandingExpressionVisitor.cs | 105 ++-- ...yableMethodTranslatingExpressionVisitor.cs | 26 +- .../Query/OwnedQueryCosmosTest.cs | 2 +- .../SimpleQueryCosmosTest.ResultOperators.cs | 2 + .../Query/SimpleQueryCosmosTest.cs | 49 +- .../BuiltInDataTypesInMemoryTest.cs | 2 +- .../ConvertToProviderTypesInMemoryTest.cs | 2 +- .../CustomConvertersInMemoryTest.cs | 8 +- .../FieldMappingInMemoryTest.cs | 82 +-- .../LazyLoadProxyInMemoryTest.cs | 8 +- .../MonsterFixupSnapshotInMemoryTest.cs | 16 +- .../Query/AsyncGearsOfWarQueryInMemoryTest.cs | 8 + .../Query/AsyncSimpleQueryInMemoryTest.cs | 6 +- .../Query/SimpleQueryInMemoryTest.cs | 134 ++++- .../SpatialInMemoryTest.cs | 2 +- .../WithConstructorsInMemoryTest.cs | 2 +- .../Query/AsyncGearsOfWarQueryTestBase.cs | 2 +- .../Query/ComplexNavigationsQueryTestBase.cs | 85 ++-- .../Query/GearsOfWarQueryTestBase.cs | 26 +- .../Query/GroupByQueryTestBase.cs | 2 +- .../Query/IncludeAsyncTestBase.cs | 2 +- .../Query/OwnedQueryTestBase.cs | 8 +- .../Query/QueryNavigationsTestBase.cs | 20 +- .../SimpleQueryTestBase.JoinGroupJoin.cs | 18 +- .../SimpleQueryTestBase.ResultOperators.cs | 4 +- .../Query/SimpleQueryTestBase.Select.cs | 35 +- .../Query/SimpleQueryTestBase.cs | 95 ++-- .../ProceduralQueryExpressionGenerator.cs | 12 - .../ComplexNavigationsQuerySqlServerTest.cs | 475 ++++++++---------- ...omplexNavigationsWeakQuerySqlServerTest.cs | 21 +- .../Query/GearsOfWarQuerySqlServerTest.cs | 188 ++++--- .../Query/GroupByQuerySqlServerTest.cs | 6 +- .../Query/OwnedQuerySqlServerTest.cs | 47 +- ...impleQuerySqlServerTest.ResultOperators.cs | 8 +- .../Query/SimpleQuerySqlServerTest.Select.cs | 34 +- .../Query/SimpleQuerySqlServerTest.cs | 186 ++++--- .../ComplexNavigationsQuerySqliteTest.cs | 84 ---- 46 files changed, 1329 insertions(+), 931 deletions(-) create mode 100644 src/EFCore.Relational/Query/SqlExpressions/CrossApplyExpression.cs create mode 100644 src/EFCore.Relational/Query/SqlExpressions/OuterApplyExpression.cs diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs index 17a935acca9..9e09505096e 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs @@ -340,7 +340,7 @@ protected override Expression VisitUnary(UnaryExpression unaryExpression) [DebuggerStepThrough] private bool TranslationFailed(Expression original, Expression translation) - => original != null && translation is EntityProjectionExpression; + => original != null && (translation == null || translation is EntityProjectionExpression); } } diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs index e7c05f398da..1a546128c04 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs @@ -38,9 +38,6 @@ public InMemoryQueryableMethodTranslatingExpressionVisitor( _model = model; } - private static Type CreateTransparentIdentifierType(Type outerType, Type innerType) - => typeof(TransparentIdentifier<,>).MakeGenericType(outerType, innerType); - public override ShapedQueryExpression TranslateSubquery(Expression expression) { return (ShapedQueryExpression)new InMemoryQueryableMethodTranslatingExpressionVisitor( @@ -217,8 +214,7 @@ protected override ShapedQueryExpression TranslateJoin(ShapedQueryExpression out outer, resultSelector, inner.ShaperExpression, - transparentIdentifierType, - false); + transparentIdentifierType); } protected override ShapedQueryExpression TranslateLastOrDefault(ShapedQueryExpression source, LambdaExpression predicate, Type returnType, bool returnDefault) @@ -250,9 +246,8 @@ protected override ShapedQueryExpression TranslateLeftJoin(ShapedQueryExpression return TranslateResultSelectorForJoin( outer, resultSelector, - inner.ShaperExpression, - transparentIdentifierType, - true); + MarkShaperNullable(inner.ShaperExpression), + transparentIdentifierType); } protected override ShapedQueryExpression TranslateLongCount(ShapedQueryExpression source, LambdaExpression predicate) @@ -360,8 +355,7 @@ protected override ShapedQueryExpression TranslateSelectMany( source, resultSelector, inner.ShaperExpression, - transparentIdentifierType, - false); + transparentIdentifierType); } } diff --git a/src/EFCore.Relational/Query/QuerySqlGenerator.cs b/src/EFCore.Relational/Query/QuerySqlGenerator.cs index 2e662f9bf57..b6eee443895 100644 --- a/src/EFCore.Relational/Query/QuerySqlGenerator.cs +++ b/src/EFCore.Relational/Query/QuerySqlGenerator.cs @@ -706,6 +706,22 @@ protected override Expression VisitCrossJoin(CrossJoinExpression crossJoinExpres return crossJoinExpression; } + protected override Expression VisitCrossApply(CrossApplyExpression crossApplyExpression) + { + _relationalCommandBuilder.Append("CROSS APPLY "); + Visit(crossApplyExpression.Table); + + return crossApplyExpression; + } + + protected override Expression VisitOuterApply(OuterApplyExpression outerApplyExpression) + { + _relationalCommandBuilder.Append("OUTER APPLY "); + Visit(outerApplyExpression.Table); + + return outerApplyExpression; + } + protected override Expression VisitInnerJoin(InnerJoinExpression innerJoinExpression) { _relationalCommandBuilder.Append("INNER JOIN "); diff --git a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs index 47060d4cedd..56107985b23 100644 --- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs @@ -242,7 +242,18 @@ protected override ShapedQueryExpression TranslateCount(ShapedQueryExpression so return source; } - protected override ShapedQueryExpression TranslateDefaultIfEmpty(ShapedQueryExpression source, Expression defaultValue) => throw new NotImplementedException(); + protected override ShapedQueryExpression TranslateDefaultIfEmpty(ShapedQueryExpression source, Expression defaultValue) + { + if (defaultValue == null) + { + ((SelectExpression)source.QueryExpression).ApplyDefaultIfEmpty(_sqlExpressionFactory); + source.ShaperExpression = MarkShaperNullable(source.ShaperExpression); + + return source; + } + + throw new NotImplementedException(); + } protected override ShapedQueryExpression TranslateDistinct(ShapedQueryExpression source) { @@ -459,8 +470,7 @@ protected override ShapedQueryExpression TranslateJoin( outer, resultSelector, inner.ShaperExpression, - transparentIdentifierType, - false); + transparentIdentifierType); } throw new NotImplementedException(); @@ -481,9 +491,8 @@ protected override ShapedQueryExpression TranslateLeftJoin(ShapedQueryExpression return TranslateResultSelectorForJoin( outer, resultSelector, - inner.ShaperExpression, - transparentIdentifierType, - true); + MarkShaperNullable(inner.ShaperExpression), + transparentIdentifierType); } throw new NotImplementedException(); @@ -710,33 +719,57 @@ protected override ShapedQueryExpression TranslateSelect(ShapedQueryExpression s return source; } - private static readonly MethodInfo _defaultIfEmptyWithoutArgMethodInfo = typeof(Enumerable).GetTypeInfo() - .GetDeclaredMethods(nameof(Enumerable.DefaultIfEmpty)).Single(mi => mi.GetParameters().Length == 1); - protected override ShapedQueryExpression TranslateSelectMany( ShapedQueryExpression source, LambdaExpression collectionSelector, LambdaExpression resultSelector) { - var collectionSelectorBody = collectionSelector.Body; - //var defaultIfEmpty = false; - - if (collectionSelectorBody is MethodCallExpression collectionEndingMethod + var defaultIfEmpty = false; + if (collectionSelector.Body is MethodCallExpression collectionEndingMethod && collectionEndingMethod.Method.IsGenericMethod - && collectionEndingMethod.Method.GetGenericMethodDefinition() == _defaultIfEmptyWithoutArgMethodInfo) + && collectionEndingMethod.Method.GetGenericMethodDefinition() == QueryableMethodProvider.DefaultIfEmptyWithoutArgumentMethodInfo) { - //defaultIfEmpty = true; - collectionSelectorBody = collectionEndingMethod.Arguments[0]; + defaultIfEmpty = true; + collectionSelector = Expression.Lambda(collectionEndingMethod.Arguments[0], collectionSelector.Parameters); } - var correlated = new CorrelationFindingExpressionVisitor().IsCorrelated(collectionSelectorBody, collectionSelector.Parameters[0]); + var correlated = new CorrelationFindingExpressionVisitor().IsCorrelated(collectionSelector); if (correlated) { - // TODO visit inner with outer parameter; - throw new NotImplementedException(); + var collectionSelectorBody = RemapLambdaBody(source, collectionSelector); + if (Visit(collectionSelectorBody) is ShapedQueryExpression inner) + { + var transparentIdentifierType = TransparentIdentifierFactory.Create( + resultSelector.Parameters[0].Type, + resultSelector.Parameters[1].Type); + + var innerShaperExpression = inner.ShaperExpression; + if (defaultIfEmpty) + { + ((SelectExpression)source.QueryExpression).AddOuterApply( + (SelectExpression)inner.QueryExpression, transparentIdentifierType); + innerShaperExpression = MarkShaperNullable(innerShaperExpression); + } + else + { + ((SelectExpression)source.QueryExpression).AddCrossApply( + (SelectExpression)inner.QueryExpression, transparentIdentifierType); + } + + return TranslateResultSelectorForJoin( + source, + resultSelector, + innerShaperExpression, + transparentIdentifierType); + } } else { - if (Visit(collectionSelectorBody) is ShapedQueryExpression inner) + if (Visit(collectionSelector.Body) is ShapedQueryExpression inner) { + if (defaultIfEmpty) + { + inner = TranslateDefaultIfEmpty(inner, null); + } + var transparentIdentifierType = TransparentIdentifierFactory.Create( resultSelector.Parameters[0].Type, resultSelector.Parameters[1].Type); @@ -748,8 +781,7 @@ protected override ShapedQueryExpression TranslateSelectMany( source, resultSelector, inner.ShaperExpression, - transparentIdentifierType, - false); + transparentIdentifierType); } } @@ -760,12 +792,14 @@ private class CorrelationFindingExpressionVisitor : ExpressionVisitor { private ParameterExpression _outerParameter; private bool _isCorrelated; - public bool IsCorrelated(Expression tree, ParameterExpression outerParameter) + + public bool IsCorrelated(LambdaExpression lambdaExpression) { + Debug.Assert(lambdaExpression.Parameters.Count == 1, "Multiparameter lambda passed to CorrelationFindingExpressionVisitor"); _isCorrelated = false; - _outerParameter = outerParameter; + _outerParameter = lambdaExpression.Parameters[0]; - Visit(tree); + Visit(lambdaExpression.Body); return _isCorrelated; } @@ -783,7 +817,16 @@ protected override Expression VisitParameter(ParameterExpression parameterExpres protected override ShapedQueryExpression TranslateSelectMany(ShapedQueryExpression source, LambdaExpression selector) { - throw new NotImplementedException(); + var innerParameter = Expression.Parameter(selector.ReturnType.TryGetSequenceType(), "i"); + var resultSelector = Expression.Lambda( + innerParameter, + new[] + { + Expression.Parameter(source.Type.TryGetSequenceType()), + innerParameter + }); + + return TranslateSelectMany(source, selector, resultSelector); } protected override ShapedQueryExpression TranslateSingleOrDefault(ShapedQueryExpression source, LambdaExpression predicate, Type returnType, bool returnDefault) diff --git a/src/EFCore.Relational/Query/SqlExpressionVisitor.cs b/src/EFCore.Relational/Query/SqlExpressionVisitor.cs index ce3dd312379..4c73e19f047 100644 --- a/src/EFCore.Relational/Query/SqlExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/SqlExpressionVisitor.cs @@ -22,6 +22,12 @@ protected override Expression VisitExtension(Expression extensionExpression) case CrossJoinExpression crossJoinExpression: return VisitCrossJoin(crossJoinExpression); + case CrossApplyExpression crossApplyExpression: + return VisitCrossApply(crossApplyExpression); + + case OuterApplyExpression outerApplyExpression: + return VisitOuterApply(outerApplyExpression); + case ExistsExpression existsExpression: return VisitExists(existsExpression); @@ -80,6 +86,8 @@ protected override Expression VisitExtension(Expression extensionExpression) protected abstract Expression VisitExists(ExistsExpression existsExpression); protected abstract Expression VisitIn(InExpression inExpression); protected abstract Expression VisitCrossJoin(CrossJoinExpression crossJoinExpression); + protected abstract Expression VisitCrossApply(CrossApplyExpression crossApplyExpression); + protected abstract Expression VisitOuterApply(OuterApplyExpression outerApplyExpression); protected abstract Expression VisitFromSql(FromSqlExpression fromSqlExpression); protected abstract Expression VisitInnerJoin(InnerJoinExpression innerJoinExpression); protected abstract Expression VisitLeftJoin(LeftJoinExpression leftJoinExpression); diff --git a/src/EFCore.Relational/Query/SqlExpressions/CrossApplyExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/CrossApplyExpression.cs new file mode 100644 index 00000000000..1f7a1ac5522 --- /dev/null +++ b/src/EFCore.Relational/Query/SqlExpressions/CrossApplyExpression.cs @@ -0,0 +1,41 @@ +// 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; + +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions +{ + public class CrossApplyExpression : JoinExpressionBase + { + public CrossApplyExpression(TableExpressionBase table) + : base(table) + { + } + + protected override Expression VisitChildren(ExpressionVisitor visitor) + => Update((TableExpressionBase)visitor.Visit(Table)); + + public virtual CrossApplyExpression Update(TableExpressionBase table) + => table != Table + ? new CrossApplyExpression(table) + : this; + + public override void Print(ExpressionPrinter expressionPrinter) + { + expressionPrinter.StringBuilder.Append("CROSS APPLY "); + expressionPrinter.Visit(Table); + } + + public override bool Equals(object obj) + => obj != null + && (ReferenceEquals(this, obj) + || obj is CrossApplyExpression crossApplyExpression + && Equals(crossApplyExpression)); + + private bool Equals(CrossApplyExpression crossApplyExpression) + => base.Equals(crossApplyExpression); + + public override int GetHashCode() => base.GetHashCode(); + } +} diff --git a/src/EFCore.Relational/Query/SqlExpressions/OuterApplyExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/OuterApplyExpression.cs new file mode 100644 index 00000000000..913896c062c --- /dev/null +++ b/src/EFCore.Relational/Query/SqlExpressions/OuterApplyExpression.cs @@ -0,0 +1,40 @@ +// 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.Linq.Expressions; + +namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions +{ + public class OuterApplyExpression : JoinExpressionBase + { + public OuterApplyExpression(TableExpressionBase table) + : base(table) + { + } + + protected override Expression VisitChildren(ExpressionVisitor visitor) + => Update((TableExpressionBase)visitor.Visit(Table)); + + public virtual OuterApplyExpression Update(TableExpressionBase table) + => table != Table + ? new OuterApplyExpression(table) + : this; + + public override void Print(ExpressionPrinter expressionPrinter) + { + expressionPrinter.StringBuilder.Append("OUTER APPLY "); + expressionPrinter.Visit(Table); + } + + public override bool Equals(object obj) + => obj != null + && (ReferenceEquals(this, obj) + || obj is OuterApplyExpression outerApplyExpression + && Equals(outerApplyExpression)); + + private bool Equals(OuterApplyExpression outerApplyExpression) + => base.Equals(outerApplyExpression); + + public override int GetHashCode() => base.GetHashCode(); + } +} diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs index 3b82f502fb4..6a2fef8a334 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs @@ -233,8 +233,7 @@ public void ApplyPredicate(SqlExpression expression) if (Limit != null || Offset != null || IsSetOperation) { - var mappings = PushdownIntoSubquery(); - expression = new SqlRemappingVisitor(mappings).Remap(expression); + expression = new SqlRemappingVisitor(PushdownIntoSubquery(), (SelectExpression)Tables[0]).Remap(expression); } if (_groupBy.Count > 0) @@ -269,7 +268,7 @@ public Expression ApplyGrouping(Expression keySelector) || keySelector is SqlParameterExpression) { PushdownIntoSubquery(); - var subquery = (SelectExpression)_tables[0]; + var subquery = (SelectExpression)Tables[0]; var projectionIndex = subquery.AddToProjection((SqlExpression)keySelector, nameof(IGrouping.Key)); keySelector = new ColumnExpression(subquery.Projection[projectionIndex], subquery); @@ -315,8 +314,8 @@ public void ApplyOrdering(OrderingExpression orderingExpression) if (IsDistinct || Limit != null || Offset != null || IsSetOperation) { orderingExpression = orderingExpression.Update( - new SqlRemappingVisitor(PushdownIntoSubquery()) - .Remap(orderingExpression.Expression)); + new SqlRemappingVisitor(PushdownIntoSubquery(), (SelectExpression)Tables[0]) + .Remap(orderingExpression.Expression)); } _orderings.Clear(); @@ -386,6 +385,54 @@ public void ApplyDistinct() ClearOrdering(); } + public void ApplyDefaultIfEmpty(ISqlExpressionFactory sqlExpressionFactory) + { + var nullSqlExpression = sqlExpressionFactory.ApplyDefaultTypeMapping( + new SqlConstantExpression(Constant(null, typeof(string)), null)); + + var dummySelectExpression = new SelectExpression( + alias: "empty", + new List { new ProjectionExpression(nullSqlExpression, "empty") }, + new List(), + new List(), + new List()); + + if (Orderings.Any() + || Limit != null + || Offset != null + || IsDistinct + || Predicate != null + || Tables.Count > 1 + || GroupBy.Count > 1) + { + PushdownIntoSubquery(); + } + + var joinPredicate = sqlExpressionFactory.Equal(sqlExpressionFactory.Constant(1), sqlExpressionFactory.Constant(1)); + var joinTable = new LeftJoinExpression(Tables.Single(), joinPredicate); + _tables.Clear(); + _tables.Add(dummySelectExpression); + _tables.Add(joinTable); + + var projectionMapping = new Dictionary(); + foreach (var projection in _projectionMapping) + { + var projectionToAdd = projection.Value; + if (projectionToAdd is EntityProjectionExpression entityProjection) + { + projectionToAdd = entityProjection.MakeNullable(); + } + else if (projectionToAdd is ColumnExpression column) + { + projectionToAdd = column.MakeNullable(); + } + + projectionMapping[projection.Key] = projectionToAdd; + } + + _projectionMapping = projectionMapping; + } + public void ClearOrdering() { _orderings.Clear(); @@ -643,7 +690,7 @@ EntityProjectionExpression liftEntityProjectionFromSubquery(EntityProjectionExpr var pendingCollections = _pendingCollections.ToList(); _pendingCollections.Clear(); - _pendingCollections.AddRange(pendingCollections.Select(new SqlRemappingVisitor(projectionMap).Remap)); + _pendingCollections.AddRange(pendingCollections.Select(new SqlRemappingVisitor(projectionMap, subquery).Remap)); _orderings.Clear(); // Only lift order by to outer if subquery does not have distinct @@ -710,7 +757,7 @@ public Expression ApplyCollectionJoin( } } - var joinPredicate = ExtractJoinKey(innerSelectExpression); + var joinPredicate = TryExtractJoinKey(innerSelectExpression); if (joinPredicate != null) { if (innerSelectExpression.Offset != null @@ -720,7 +767,8 @@ public Expression ApplyCollectionJoin( || innerSelectExpression.Tables.Count > 1 || innerSelectExpression.GroupBy.Count > 1) { - var sqlRemappingVisitor = new SqlRemappingVisitor(innerSelectExpression.PushdownIntoSubquery()); + var sqlRemappingVisitor = new SqlRemappingVisitor(innerSelectExpression.PushdownIntoSubquery(), + (SelectExpression)innerSelectExpression.Tables[0]); joinPredicate = sqlRemappingVisitor.Remap(joinPredicate); } @@ -829,11 +877,11 @@ private object GetProjectionIndex(ProjectionBindingExpression projectionBindingE } } - private SqlExpression ExtractJoinKey(SelectExpression selectExpression) + private SqlExpression TryExtractJoinKey(SelectExpression selectExpression) { if (selectExpression.Predicate != null) { - var joinPredicate = ExtractJoinKey(selectExpression, selectExpression.Predicate, out var predicate); + var joinPredicate = TryExtractJoinKey(selectExpression, selectExpression.Predicate, out var predicate); selectExpression.Predicate = predicate; return joinPredicate; @@ -842,7 +890,7 @@ private SqlExpression ExtractJoinKey(SelectExpression selectExpression) return null; } - private SqlExpression ExtractJoinKey(SelectExpression selectExpression, SqlExpression predicate, out SqlExpression updatedPredicate) + private SqlExpression TryExtractJoinKey(SelectExpression selectExpression, SqlExpression predicate, out SqlExpression updatedPredicate) { if (predicate is SqlBinaryExpression sqlBinaryExpression) { @@ -865,8 +913,8 @@ static SqlExpression combineNonNullExpressions(SqlExpression left, SqlExpression : right; } - var leftJoinKey = ExtractJoinKey(selectExpression, sqlBinaryExpression.Left, out var leftPredicate); - var rightJoinKey = ExtractJoinKey(selectExpression, sqlBinaryExpression.Right, out var rightPredicate); + var leftJoinKey = TryExtractJoinKey(selectExpression, sqlBinaryExpression.Left, out var leftPredicate); + var rightJoinKey = TryExtractJoinKey(selectExpression, sqlBinaryExpression.Right, out var rightPredicate); updatedPredicate = combineNonNullExpressions(leftPredicate, rightPredicate); @@ -888,14 +936,12 @@ private SqlBinaryExpression ValidateKeyComparison(SelectExpression inner, SqlBin if (ContainsTableReference(leftColumn.Table) && inner.ContainsTableReference(rightColumn.Table)) { - inner.AddToProjection(rightColumn); return sqlBinaryExpression; } if (ContainsTableReference(rightColumn.Table) && inner.ContainsTableReference(leftColumn.Table)) { - inner.AddToProjection(leftColumn); return sqlBinaryExpression.Update( sqlBinaryExpression.Right, sqlBinaryExpression.Left); @@ -917,7 +963,7 @@ public void AddInnerJoin(SelectExpression innerSelectExpression, SqlExpression j { if (Limit != null || Offset != null || IsDistinct || IsSetOperation || GroupBy.Count > 1) { - joinPredicate = new SqlRemappingVisitor(PushdownIntoSubquery()) + joinPredicate = new SqlRemappingVisitor(PushdownIntoSubquery(), (SelectExpression)Tables[0]) .Remap(joinPredicate); } @@ -931,7 +977,8 @@ public void AddInnerJoin(SelectExpression innerSelectExpression, SqlExpression j || innerSelectExpression.Tables.Count > 1 || innerSelectExpression.GroupBy.Count > 1) { - joinPredicate = new SqlRemappingVisitor(innerSelectExpression.PushdownIntoSubquery()) + joinPredicate = new SqlRemappingVisitor( + innerSelectExpression.PushdownIntoSubquery(), (SelectExpression)innerSelectExpression.Tables[0]) .Remap(joinPredicate); } @@ -959,7 +1006,7 @@ public void AddLeftJoin(SelectExpression innerSelectExpression, SqlExpression jo { if (Limit != null || Offset != null || IsDistinct || IsSetOperation || GroupBy.Count > 1) { - joinPredicate = new SqlRemappingVisitor(PushdownIntoSubquery()) + joinPredicate = new SqlRemappingVisitor(PushdownIntoSubquery(), (SelectExpression)Tables[0]) .Remap(joinPredicate); } @@ -971,7 +1018,8 @@ public void AddLeftJoin(SelectExpression innerSelectExpression, SqlExpression jo || innerSelectExpression.Tables.Count > 1 || innerSelectExpression.GroupBy.Count > 1) { - joinPredicate = new SqlRemappingVisitor(innerSelectExpression.PushdownIntoSubquery()) + joinPredicate = new SqlRemappingVisitor( + innerSelectExpression.PushdownIntoSubquery(), (SelectExpression)innerSelectExpression.Tables[0]) .Remap(joinPredicate); } @@ -1045,12 +1093,118 @@ public void AddCrossJoin(SelectExpression innerSelectExpression, Type transparen _projectionMapping = projectionMapping; } + public void AddCrossApply(SelectExpression innerSelectExpression, Type transparentIdentifierType) + { + var joinPredicate = TryExtractJoinKey(innerSelectExpression); + if (joinPredicate != null) + { + // TODO: Make sure that innerSelectExpression does not contain any reference from this SelectExpression + AddInnerJoin(innerSelectExpression, joinPredicate, transparentIdentifierType); + return; + } + + if (Limit != null || Offset != null || IsDistinct || Predicate != null || IsSetOperation || GroupBy.Count > 1) + { + innerSelectExpression = new SqlRemappingVisitor( + PushdownIntoSubquery(), (SelectExpression)Tables[0]).Remap(innerSelectExpression); + } + + if (innerSelectExpression.Orderings.Any() + || innerSelectExpression.Limit != null + || innerSelectExpression.Offset != null + || innerSelectExpression.IsDistinct + || innerSelectExpression.Predicate != null + || innerSelectExpression.Tables.Count > 1 + || innerSelectExpression.GroupBy.Count > 1) + { + innerSelectExpression.PushdownIntoSubquery(); + } + + _identifier.AddRange(innerSelectExpression._identifier); + var joinTable = new CrossApplyExpression(innerSelectExpression.Tables.Single()); + _tables.Add(joinTable); + + var outerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Outer"); + var projectionMapping = new Dictionary(); + foreach (var projection in _projectionMapping) + { + projectionMapping[projection.Key.Prepend(outerMemberInfo)] = projection.Value; + } + + var innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); + foreach (var projection in innerSelectExpression._projectionMapping) + { + projectionMapping[projection.Key.Prepend(innerMemberInfo)] = projection.Value; + } + + _projectionMapping = projectionMapping; + } + + public void AddOuterApply(SelectExpression innerSelectExpression, Type transparentIdentifierType) + { + var joinPredicate = TryExtractJoinKey(innerSelectExpression); + if (joinPredicate != null) + { + // TODO: Make sure that innerSelectExpression does not contain any reference from this SelectExpression + AddLeftJoin(innerSelectExpression, joinPredicate, transparentIdentifierType); + return; + } + + if (Limit != null || Offset != null || IsDistinct || Predicate != null || IsSetOperation || GroupBy.Count > 1) + { + innerSelectExpression = new SqlRemappingVisitor( + PushdownIntoSubquery(), (SelectExpression)Tables[0]).Remap(innerSelectExpression); + } + + if (innerSelectExpression.Orderings.Any() + || innerSelectExpression.Limit != null + || innerSelectExpression.Offset != null + || innerSelectExpression.IsDistinct + || innerSelectExpression.Predicate != null + || innerSelectExpression.Tables.Count > 1 + || innerSelectExpression.GroupBy.Count > 1) + { + innerSelectExpression.PushdownIntoSubquery(); + } + + _identifier.AddRange(innerSelectExpression._identifier); + var joinTable = new OuterApplyExpression(innerSelectExpression.Tables.Single()); + _tables.Add(joinTable); + + var outerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Outer"); + var projectionMapping = new Dictionary(); + foreach (var projection in _projectionMapping) + { + projectionMapping[projection.Key.Prepend(outerMemberInfo)] = projection.Value; + } + + var innerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); + foreach (var projection in innerSelectExpression._projectionMapping) + { + var projectionToAdd = projection.Value; + if (projectionToAdd is EntityProjectionExpression entityProjection) + { + projectionToAdd = entityProjection.MakeNullable(); + } + else if (projectionToAdd is ColumnExpression column) + { + projectionToAdd = column.MakeNullable(); + } + + projectionMapping[projection.Key.Prepend(innerMemberInfo)] = projectionToAdd; + } + + _projectionMapping = projectionMapping; + } + private class SqlRemappingVisitor : ExpressionVisitor { + private readonly SelectExpression _subquery; private readonly IDictionary _mappings; - public SqlRemappingVisitor(IDictionary mappings) + public SqlRemappingVisitor(IDictionary mappings, SelectExpression subquery) { + _subquery = subquery; _mappings = mappings; } @@ -1059,13 +1213,21 @@ public SqlRemappingVisitor(IDictionary mappings public override Expression Visit(Expression expression) { - if (expression is SqlExpression sqlExpression - && _mappings.TryGetValue(sqlExpression, out var outer)) + switch (expression) { - return outer; + case SqlExpression sqlExpression + when _mappings.TryGetValue(sqlExpression, out var outer): + return outer; + + case ColumnExpression columnExpression + when _subquery.ContainsTableReference(columnExpression.Table): + var index = _subquery.AddToProjection(columnExpression); + var projectionExpression = _subquery._projection[index]; + return new ColumnExpression(projectionExpression, _subquery); + + default: + return base.Visit(expression); } - - return base.Visit(expression); } } diff --git a/src/EFCore.SqlServer/Query/Internal/SearchConditionConvertingExpressionVisitor.cs b/src/EFCore.SqlServer/Query/Internal/SearchConditionConvertingExpressionVisitor.cs index 517c095c29c..c718dfb1894 100644 --- a/src/EFCore.SqlServer/Query/Internal/SearchConditionConvertingExpressionVisitor.cs +++ b/src/EFCore.SqlServer/Query/Internal/SearchConditionConvertingExpressionVisitor.cs @@ -317,6 +317,26 @@ protected override Expression VisitCrossJoin(CrossJoinExpression crossJoinExpres return crossJoinExpression.Update(table); } + protected override Expression VisitCrossApply(CrossApplyExpression crossApplyExpression) + { + var parentSearchCondition = _isSearchCondition; + _isSearchCondition = false; + var table = (TableExpressionBase)Visit(crossApplyExpression.Table); + _isSearchCondition = parentSearchCondition; + + return crossApplyExpression.Update(table); + } + + protected override Expression VisitOuterApply(OuterApplyExpression outerApplyExpression) + { + var parentSearchCondition = _isSearchCondition; + _isSearchCondition = false; + var table = (TableExpressionBase)Visit(outerApplyExpression.Table); + _isSearchCondition = parentSearchCondition; + + return outerApplyExpression.Update(table); + } + protected override Expression VisitInnerJoin(InnerJoinExpression innerJoinExpression) { var parentSearchCondition = _isSearchCondition; diff --git a/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.cs b/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.cs index a5d9c229992..837a3c2d3f3 100644 --- a/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.cs +++ b/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.cs @@ -361,41 +361,40 @@ when QueryableMethodProvider.IsSumWithSelectorMethodInfo(method): case nameof(Queryable.Join) when genericMethod == QueryableMethodProvider.JoinMethodInfo: + { + var secondArgument = Visit(methodCallExpression.Arguments[1]); + if (secondArgument is NavigationExpansionExpression innerSource) { - var secondArgument = Visit(methodCallExpression.Arguments[1]); - if (secondArgument is NavigationExpansionExpression innerSource) - { - return ProcessJoin( - source, - innerSource, - methodCallExpression.Arguments[2].UnwrapLambdaFromQuote(), - methodCallExpression.Arguments[3].UnwrapLambdaFromQuote(), - methodCallExpression.Arguments[4].UnwrapLambdaFromQuote()); - } - break; + return ProcessJoin( + source, + innerSource, + methodCallExpression.Arguments[2].UnwrapLambdaFromQuote(), + methodCallExpression.Arguments[3].UnwrapLambdaFromQuote(), + methodCallExpression.Arguments[4].UnwrapLambdaFromQuote()); } + break; + } case nameof(QueryableExtensions.LeftJoin) when genericMethod == QueryableExtensions.LeftJoinMethodInfo: + { + var secondArgument = Visit(methodCallExpression.Arguments[1]); + if (secondArgument is NavigationExpansionExpression innerSource) { - var secondArgument = Visit(methodCallExpression.Arguments[1]); - if (secondArgument is NavigationExpansionExpression innerSource) - { - return ProcessLeftJoin( - source, - innerSource, - methodCallExpression.Arguments[2].UnwrapLambdaFromQuote(), - methodCallExpression.Arguments[3].UnwrapLambdaFromQuote(), - methodCallExpression.Arguments[4].UnwrapLambdaFromQuote()); - } - break; + return ProcessLeftJoin( + source, + innerSource, + methodCallExpression.Arguments[2].UnwrapLambdaFromQuote(), + methodCallExpression.Arguments[3].UnwrapLambdaFromQuote(), + methodCallExpression.Arguments[4].UnwrapLambdaFromQuote()); } + break; + } case nameof(Queryable.SelectMany) when genericMethod == QueryableMethodProvider.SelectManyWithoutCollectionSelectorMethodInfo: return ProcessSelectMany( source, - genericMethod, methodCallExpression.Arguments[1].UnwrapLambdaFromQuote(), null); @@ -403,7 +402,6 @@ when QueryableMethodProvider.IsSumWithSelectorMethodInfo(method): when genericMethod == QueryableMethodProvider.SelectManyWithCollectionSelectorMethodInfo: return ProcessSelectMany( source, - genericMethod, methodCallExpression.Arguments[1].UnwrapLambdaFromQuote(), methodCallExpression.Arguments[2].UnwrapLambdaFromQuote()); @@ -415,17 +413,17 @@ when QueryableMethodProvider.IsSumWithSelectorMethodInfo(method): when genericMethod == QueryableMethodProvider.IntersectMethodInfo: case nameof(Queryable.Union) when genericMethod == QueryableMethodProvider.UnionMethodInfo: + { + var secondArgument = Visit(methodCallExpression.Arguments[1]); + if (secondArgument is NavigationExpansionExpression innerSource) { - var secondArgument = Visit(methodCallExpression.Arguments[1]); - if (secondArgument is NavigationExpansionExpression innerSource) - { - return ProcessSetOperation( - source, - genericMethod, - innerSource); - } - break; + return ProcessSetOperation( + source, + genericMethod, + innerSource); } + break; + } case nameof(Queryable.Cast) when genericMethod == QueryableMethodProvider.CastMethodInfo: @@ -508,6 +506,10 @@ when QueryableMethodProvider.IsSumWithSelectorMethodInfo(method): source, methodCallExpression.Arguments[1].UnwrapLambdaFromQuote()); + case nameof(Queryable.DefaultIfEmpty) + when genericMethod == QueryableMethodProvider.DefaultIfEmptyWithoutArgumentMethodInfo: + return ProcessDefaultIfEmpty(source); + default: throw new NotImplementedException($"Unhandled method in navigation expansion: {method.Name}"); } @@ -569,6 +571,18 @@ when QueryableMethodProvider.IsSumWithSelectorMethodInfo(method): return ProcessUnknownMethod(methodCallExpression); } + private Expression ProcessDefaultIfEmpty(NavigationExpansionExpression source) + { + source.UpdateSource( + Expression.Call( + QueryableMethodProvider.DefaultIfEmptyWithoutArgumentMethodInfo.MakeGenericMethod(source.SourceElementType), + source.Source)); + + _entityReferenceOptionalMarkingExpressionVisitor.Visit(source.PendingSelector); + + return source; + } + private Expression ProcessUnknownMethod(MethodCallExpression methodCallExpression) { var queryableElementType = methodCallExpression.Type.TryGetElementType(typeof(IQueryable<>)); @@ -721,11 +735,15 @@ private IEnumerable FindNavigations(IEntityType entityType, string private Expression ProcessSelectMany( NavigationExpansionExpression source, - MethodInfo genericMethod, LambdaExpression collectionSelector, LambdaExpression resultSelector) { var collectionSelectorBody = ExpandNavigationsInLambdaExpression(source, collectionSelector); + if (collectionSelectorBody is MaterializeCollectionNavigationExpression materializeCollectionNavigationExpression) + { + collectionSelectorBody = materializeCollectionNavigationExpression.Subquery; + } + if (collectionSelectorBody is NavigationExpansionExpression collectionSource) { collectionSource = (NavigationExpansionExpression)_pendingSelectorExpandingExpressionVisitor.Visit(collectionSource); @@ -746,10 +764,8 @@ private Expression ProcessSelectMany( var transparentIdentifierType = TransparentIdentifierFactory.Create( source.SourceElementType, collectionElementType); - var transparentIdentifierOuterMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Outer"); var transparentIdentifierInnerMemberInfo = transparentIdentifierType.GetTypeInfo().GetDeclaredField("Inner"); - var collectionElementParameter = Expression.Parameter(collectionElementType, "c"); var newResultSelector = Expression.Lambda( @@ -761,20 +777,21 @@ private Expression ProcessSelectMany( collectionElementParameter); var newSource = Expression.Call( - genericMethod.MakeGenericMethod( + QueryableMethodProvider.SelectManyWithCollectionSelectorMethodInfo.MakeGenericMethod( source.SourceElementType, collectionElementType, newResultSelector.ReturnType), source.Source, Expression.Quote(collectionSelector), Expression.Quote(newResultSelector)); - var currentTree = new NavigationTreeNode(source.CurrentTree, innerTree); - var pendingSelector = new ReplacingExpressionVisitor( - new Dictionary - { - { resultSelector.Parameters[0], source.PendingSelector }, - { resultSelector.Parameters[1], innerTree } - }).Visit(resultSelector.Body); + var pendingSelector = resultSelector == null + ? innerTree + : new ReplacingExpressionVisitor( + new Dictionary + { + { resultSelector.Parameters[0], source.PendingSelector }, + { resultSelector.Parameters[1], innerTree } + }).Visit(resultSelector.Body); var parameterName = GetParameterName("ti"); return new NavigationExpansionExpression(newSource, currentTree, pendingSelector, parameterName); diff --git a/src/EFCore/Query/QueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore/Query/QueryableMethodTranslatingExpressionVisitor.cs index 50796808d15..191d3b2c7ed 100644 --- a/src/EFCore/Query/QueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore/Query/QueryableMethodTranslatingExpressionVisitor.cs @@ -13,6 +13,7 @@ namespace Microsoft.EntityFrameworkCore.Query public abstract class QueryableMethodTranslatingExpressionVisitor : ExpressionVisitor { private readonly bool _subquery; + private readonly EntityShaperNullableMarkingExpressionVisitor _entityShaperNullableMarkingExpressionVisitor; protected QueryableMethodTranslatingExpressionVisitor( QueryableMethodTranslatingExpressionVisitorDependencies dependencies, @@ -20,6 +21,7 @@ protected QueryableMethodTranslatingExpressionVisitor( { Dependencies = dependencies; _subquery = subquery; + _entityShaperNullableMarkingExpressionVisitor = new EntityShaperNullableMarkingExpressionVisitor(); } protected virtual QueryableMethodTranslatingExpressionVisitorDependencies Dependencies { get; } @@ -374,27 +376,21 @@ private class EntityShaperNullableMarkingExpressionVisitor : ExpressionVisitor { protected override Expression VisitExtension(Expression extensionExpression) { - if (extensionExpression is EntityShaperExpression entityShaper) - { - return entityShaper.MarkAsNullable(); - } - - return base.VisitExtension(extensionExpression); + return extensionExpression is EntityShaperExpression entityShaper + ? entityShaper.MarkAsNullable() + : base.VisitExtension(extensionExpression); } } + protected virtual Expression MarkShaperNullable(Expression shaperExpression) + => _entityShaperNullableMarkingExpressionVisitor.Visit(shaperExpression); + protected virtual ShapedQueryExpression TranslateResultSelectorForJoin( ShapedQueryExpression outer, LambdaExpression resultSelector, Expression innerShaper, - Type transparentIdentifierType, - bool innerNullable) + Type transparentIdentifierType) { - if (innerNullable) - { - innerShaper = new EntityShaperNullableMarkingExpressionVisitor().Visit(innerShaper); - } - outer.ShaperExpression = CombineShapers( outer.QueryExpression, outer.ShaperExpression, @@ -404,9 +400,9 @@ protected virtual ShapedQueryExpression TranslateResultSelectorForJoin( var transparentIdentifierParameter = Expression.Parameter(transparentIdentifierType); Expression original1 = resultSelector.Parameters[0]; - Expression replacement1 = AccessOuterTransparentField(transparentIdentifierType, transparentIdentifierParameter); + var replacement1 = AccessOuterTransparentField(transparentIdentifierType, transparentIdentifierParameter); Expression original2 = resultSelector.Parameters[1]; - Expression replacement2 = AccessInnerTransparentField(transparentIdentifierType, transparentIdentifierParameter); + var replacement2 = AccessInnerTransparentField(transparentIdentifierType, transparentIdentifierParameter); var newResultSelector = Expression.Lambda( new ReplacingExpressionVisitor( new Dictionary { diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/OwnedQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/OwnedQueryCosmosTest.cs index b68001ddfd6..95a611d94ee 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/OwnedQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/OwnedQueryCosmosTest.cs @@ -25,7 +25,7 @@ public override void Query_loads_reference_nav_automatically_in_projection() { } - [ConditionalFact(Skip = "Issue#15711")] + [ConditionalFact(Skip = "SelectMany #12086")] public override void Query_with_owned_entity_equality_operator() { base.Query_with_owned_entity_equality_operator(); diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/SimpleQueryCosmosTest.ResultOperators.cs b/test/EFCore.Cosmos.FunctionalTests/Query/SimpleQueryCosmosTest.ResultOperators.cs index 7754276ff66..41e4b53c96f 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/SimpleQueryCosmosTest.ResultOperators.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/SimpleQueryCosmosTest.ResultOperators.cs @@ -1159,6 +1159,7 @@ FROM root c WHERE (c[""Discriminator""] = ""OrderDetail"")"); } + [ConditionalFact(Skip = "Issue #14935")] public override void OfType_Select() { base.OfType_Select(); @@ -1169,6 +1170,7 @@ FROM root c WHERE (c[""Discriminator""] = ""Order"")"); } + [ConditionalFact(Skip = "Issue #14935")] public override void OfType_Select_OfType_Select() { base.OfType_Select_OfType_Select(); diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/SimpleQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/SimpleQueryCosmosTest.cs index 54f71a8cc32..4e7e7eb8795 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/SimpleQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/SimpleQueryCosmosTest.cs @@ -228,6 +228,7 @@ FROM root c WHERE (c[""Discriminator""] = ""Customer"")"); } + [ConditionalTheory(Skip = "Issue#14935")] public override async Task Default_if_empty_top_level(bool isAsync) { await base.Default_if_empty_top_level(isAsync); @@ -238,6 +239,7 @@ FROM root c WHERE ((c[""Discriminator""] = ""Employee"") AND (c[""EmployeeID""] = 4294967295))"); } + [ConditionalTheory(Skip = "Issue#14935")] public override async Task Join_with_default_if_empty_on_both_sources(bool isAsync) { await base.Join_with_default_if_empty_on_both_sources(isAsync); @@ -248,6 +250,7 @@ FROM root c WHERE (c[""Discriminator""] = ""Customer"")"); } + [ConditionalTheory(Skip = "Issue#14935")] public override async Task Default_if_empty_top_level_followed_by_projecting_constant(bool isAsync) { await base.Default_if_empty_top_level_followed_by_projecting_constant(isAsync); @@ -258,6 +261,7 @@ FROM root c WHERE (c[""Discriminator""] = ""Customer"")"); } + [ConditionalTheory(Skip = "Issue#14935")] public override async Task Default_if_empty_top_level_positive(bool isAsync) { await base.Default_if_empty_top_level_positive(isAsync); @@ -284,6 +288,7 @@ FROM root c WHERE (c[""Discriminator""] = ""Customer"")"); } + [ConditionalTheory(Skip = "Issue#14935")] public override async Task Default_if_empty_top_level_projection(bool isAsync) { await base.Default_if_empty_top_level_projection(isAsync); @@ -1887,6 +1892,7 @@ FROM root c WHERE (c[""Discriminator""] = ""Customer"")"); } + [ConditionalTheory(Skip = "Issue #14935")] public override async Task Select_DTO_with_member_init_distinct_in_subquery_translated_to_server(bool isAsync) { await base.Select_DTO_with_member_init_distinct_in_subquery_translated_to_server(isAsync); @@ -1968,6 +1974,7 @@ FROM root c WHERE ((c[""Discriminator""] = ""Product"") AND (c[""ProductID""] = 72))"); } + [ConditionalTheory(Skip = "Issue #14935")] public override async Task Select_many_cross_join_same_collection(bool isAsync) { await base.Select_many_cross_join_same_collection(isAsync); @@ -2562,6 +2569,7 @@ FROM root c WHERE ((c[""Discriminator""] = ""Order"") AND (c[""OrderDate""] != null))"); } + [ConditionalFact(Skip = "Issue#14935")] public override void DefaultIfEmpty_without_group_join() { base.DefaultIfEmpty_without_group_join(); @@ -2572,6 +2580,7 @@ FROM root c WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""City""] = ""London""))"); } + [ConditionalTheory(Skip = "Issue#14935")] public override async Task DefaultIfEmpty_in_subquery(bool isAsync) { await AssertQuery( @@ -2593,6 +2602,13 @@ FROM root c WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""City""] = ""London""))"); } + [ConditionalTheory(Skip = "Issue#14935")] + public override Task DefaultIfEmpty_in_subquery_not_correlated(bool isAsync) + { + return base.DefaultIfEmpty_in_subquery_not_correlated(isAsync); + } + + [ConditionalTheory(Skip = "Issue#14935")] public override async Task DefaultIfEmpty_in_subquery_nested(bool isAsync) { await AssertQuery( @@ -4038,12 +4054,39 @@ public override Task Navigation_inside_interpolated_string_is_expanded(bool isAs return base.Navigation_inside_interpolated_string_is_expanded(isAsync); } + [ConditionalTheory(Skip = "Issue #14935")] + public override Task Select_DTO_with_member_init_distinct_in_subquery_translated_to_server_2(bool isAsync) + { + return base.Select_DTO_with_member_init_distinct_in_subquery_translated_to_server_2(isAsync); + } + + [ConditionalTheory(Skip = "Issue #14935")] + public override Task SelectMany_without_result_selector_naked_collection_navigation(bool isAsync) + { + return base.SelectMany_without_result_selector_naked_collection_navigation(isAsync); + } + + [ConditionalTheory(Skip = "Issue #14935")] + public override Task SelectMany_without_result_selector_collection_navigation_composed(bool isAsync) + { + return base.SelectMany_without_result_selector_collection_navigation_composed(isAsync); + } + + [ConditionalTheory(Skip = "Issue #14935")] + public override Task SelectMany_correlated_subquery_simple(bool isAsync) + { + return base.SelectMany_correlated_subquery_simple(isAsync); + } + + [ConditionalTheory(Skip = "Issue#14935")] + public override Task Multiple_select_many_with_predicate(bool isAsync) + { + return base.Multiple_select_many_with_predicate(isAsync); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); - private void AssertContainsSql(params string[] expected) - => Fixture.TestSqlLoggerFactory.AssertBaseline(expected, assertOrder: false); - protected override void ClearLog() => Fixture.TestSqlLoggerFactory.Clear(); } diff --git a/test/EFCore.InMemory.FunctionalTests/BuiltInDataTypesInMemoryTest.cs b/test/EFCore.InMemory.FunctionalTests/BuiltInDataTypesInMemoryTest.cs index 15240ed70c8..3fa64fc7c23 100644 --- a/test/EFCore.InMemory.FunctionalTests/BuiltInDataTypesInMemoryTest.cs +++ b/test/EFCore.InMemory.FunctionalTests/BuiltInDataTypesInMemoryTest.cs @@ -16,7 +16,7 @@ public BuiltInDataTypesInMemoryTest(BuiltInDataTypesInMemoryFixture fixture) { } - [ConditionalFact(Skip = "Issue#15711")] + [ConditionalFact(Skip = "Issue#16963")] public override void Can_insert_and_read_back_with_string_key() { base.Can_insert_and_read_back_with_string_key(); diff --git a/test/EFCore.InMemory.FunctionalTests/ConvertToProviderTypesInMemoryTest.cs b/test/EFCore.InMemory.FunctionalTests/ConvertToProviderTypesInMemoryTest.cs index 11a10cd6a3c..c4e2cc38e52 100644 --- a/test/EFCore.InMemory.FunctionalTests/ConvertToProviderTypesInMemoryTest.cs +++ b/test/EFCore.InMemory.FunctionalTests/ConvertToProviderTypesInMemoryTest.cs @@ -15,7 +15,7 @@ public ConvertToProviderTypesInMemoryTest(ConvertToProviderTypesInMemoryFixture { } - [ConditionalFact(Skip = "Issue#15711")] + [ConditionalFact(Skip = "Issue#16963")] public override void Can_insert_and_read_back_with_string_key() { base.Can_insert_and_read_back_with_string_key(); diff --git a/test/EFCore.InMemory.FunctionalTests/CustomConvertersInMemoryTest.cs b/test/EFCore.InMemory.FunctionalTests/CustomConvertersInMemoryTest.cs index afdab0bd66d..b64525cfe2d 100644 --- a/test/EFCore.InMemory.FunctionalTests/CustomConvertersInMemoryTest.cs +++ b/test/EFCore.InMemory.FunctionalTests/CustomConvertersInMemoryTest.cs @@ -19,18 +19,12 @@ public override void Can_insert_and_read_back_with_case_insensitive_string_key() { } - [ConditionalFact(Skip = "Issue#15711")] + [ConditionalFact(Skip = "Issue#16963")] public override void Can_insert_and_read_back_with_string_key() { base.Can_insert_and_read_back_with_string_key(); } - [ConditionalFact(Skip = "Issue#15711")] - public override void Can_query_and_update_with_nullable_converter_on_primary_key() - { - base.Can_query_and_update_with_nullable_converter_on_primary_key(); - } - public class CustomConvertersInMemoryFixture : CustomConvertersFixtureBase { public override bool StrictEquality => true; diff --git a/test/EFCore.InMemory.FunctionalTests/FieldMappingInMemoryTest.cs b/test/EFCore.InMemory.FunctionalTests/FieldMappingInMemoryTest.cs index 812484f77fa..5c43740b376 100644 --- a/test/EFCore.InMemory.FunctionalTests/FieldMappingInMemoryTest.cs +++ b/test/EFCore.InMemory.FunctionalTests/FieldMappingInMemoryTest.cs @@ -14,132 +14,72 @@ public FieldMappingInMemoryTest(FieldMappingInMemoryFixture fixture) { } - [ConditionalFact(Skip = "Issue#15711")] + [ConditionalFact(Skip = "Issue#16963")] public override void Field_mapping_with_conversion_does_not_throw() { base.Field_mapping_with_conversion_does_not_throw(); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory(Skip = "Issue#16963")] public override void Include_collection_auto_props(bool tracking) { base.Include_collection_auto_props(tracking); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory(Skip = "Issue#16963")] public override void Include_collection_fields_only(bool tracking) { base.Include_collection_fields_only(tracking); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory(Skip = "Issue#16963")] public override void Include_collection_fields_only_for_navs_too(bool tracking) { base.Include_collection_fields_only_for_navs_too(tracking); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory(Skip = "Issue#16963")] public override void Include_collection_full_props(bool tracking) { base.Include_collection_full_props(tracking); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory(Skip = "Issue#16963")] public override void Include_collection_full_props_with_named_fields(bool tracking) { base.Include_collection_full_props_with_named_fields(tracking); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory(Skip = "Issue#16963")] public override void Include_collection_hiding_props(bool tracking) { base.Include_collection_hiding_props(tracking); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory(Skip = "Issue#16963")] public override void Include_collection_read_only_props(bool tracking) { base.Include_collection_read_only_props(tracking); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory(Skip = "Issue#16963")] public override void Include_collection_read_only_props_with_named_fields(bool tracking) { base.Include_collection_read_only_props_with_named_fields(tracking); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory(Skip = "Issue#16963")] public override void Include_collection_write_only_props(bool tracking) { base.Include_collection_write_only_props(tracking); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory(Skip = "Issue#16963")] public override void Include_collection_write_only_props_with_named_fields(bool tracking) { base.Include_collection_write_only_props_with_named_fields(tracking); } - [ConditionalTheory(Skip = "Issue#15711")] - public override void Include_reference_auto_props(bool tracking) - { - base.Include_reference_auto_props(tracking); - } - - [ConditionalTheory(Skip = "Issue#15711")] - public override void Include_reference_fields_only(bool tracking) - { - base.Include_reference_fields_only(tracking); - } - - [ConditionalTheory(Skip = "Issue#15711")] - public override void Include_reference_fields_only_only_for_navs_too(bool tracking) - { - base.Include_reference_fields_only_only_for_navs_too(tracking); - } - - [ConditionalTheory(Skip = "Issue#15711")] - public override void Include_reference_full_props(bool tracking) - { - base.Include_reference_full_props(tracking); - } - - [ConditionalTheory(Skip = "Issue#15711")] - public override void Include_reference_full_props_with_named_fields(bool tracking) - { - base.Include_reference_full_props_with_named_fields(tracking); - } - - [ConditionalTheory(Skip = "Issue#15711")] - public override void Include_reference_hiding_props(bool tracking) - { - base.Include_reference_hiding_props(tracking); - } - - [ConditionalTheory(Skip = "Issue#15711")] - public override void Include_reference_read_only_props(bool tracking) - { - base.Include_reference_read_only_props(tracking); - } - - [ConditionalTheory(Skip = "Issue#15711")] - public override void Include_reference_read_only_props_with_named_fields(bool tracking) - { - base.Include_reference_read_only_props_with_named_fields(tracking); - } - - [ConditionalTheory(Skip = "Issue#15711")] - public override void Include_reference_write_only_props(bool tracking) - { - base.Include_reference_write_only_props(tracking); - } - - [ConditionalTheory(Skip = "Issue#15711")] - public override void Include_reference_write_only_props_with_named_fields(bool tracking) - { - base.Include_reference_write_only_props_with_named_fields(tracking); - } - protected override void Update(string navigation) { base.Update(navigation); diff --git a/test/EFCore.InMemory.FunctionalTests/LazyLoadProxyInMemoryTest.cs b/test/EFCore.InMemory.FunctionalTests/LazyLoadProxyInMemoryTest.cs index f089d481efd..efe535cda0c 100644 --- a/test/EFCore.InMemory.FunctionalTests/LazyLoadProxyInMemoryTest.cs +++ b/test/EFCore.InMemory.FunctionalTests/LazyLoadProxyInMemoryTest.cs @@ -14,25 +14,25 @@ public LazyLoadProxyInMemoryTest(LoadInMemoryFixture fixture) { } - [ConditionalTheory(Skip = "Owned Issue#15711")] + [ConditionalFact(Skip = "Issue#16963")] public override void Lazy_loading_finds_correct_entity_type_with_already_loaded_owned_types() { base.Lazy_loading_finds_correct_entity_type_with_already_loaded_owned_types(); } - [ConditionalTheory(Skip = "Owned Issue#15711")] + [ConditionalFact(Skip = "Issue#16963")] public override void Lazy_loading_finds_correct_entity_type_with_alternate_model() { base.Lazy_loading_finds_correct_entity_type_with_alternate_model(); } - [ConditionalTheory(Skip = "Owned Issue#15711")] + [ConditionalFact(Skip = "Issue#16963")] public override void Lazy_loading_finds_correct_entity_type_with_multiple_queries() { base.Lazy_loading_finds_correct_entity_type_with_multiple_queries(); } - [ConditionalTheory(Skip = "Owned Issue#15711")] + [ConditionalFact(Skip = "Issue#16963")] public override void Lazy_loading_finds_correct_entity_type_with_opaque_predicate_and_multiple_queries() { base.Lazy_loading_finds_correct_entity_type_with_opaque_predicate_and_multiple_queries(); diff --git a/test/EFCore.InMemory.FunctionalTests/MonsterFixupSnapshotInMemoryTest.cs b/test/EFCore.InMemory.FunctionalTests/MonsterFixupSnapshotInMemoryTest.cs index e754e0fdb52..7225c16f09d 100644 --- a/test/EFCore.InMemory.FunctionalTests/MonsterFixupSnapshotInMemoryTest.cs +++ b/test/EFCore.InMemory.FunctionalTests/MonsterFixupSnapshotInMemoryTest.cs @@ -14,49 +14,49 @@ public MonsterFixupSnapshotInMemoryTest(MonsterFixupSnapshotInMemoryFixture fixt { } - [ConditionalFact(Skip = "Include Issue#15711")] + [ConditionalFact(Skip = "Issue#16963")] public override void Can_build_monster_model_and_seed_data_using_all_navigations() { base.Can_build_monster_model_and_seed_data_using_all_navigations(); } - [ConditionalFact(Skip = "Include Issue#15711")] + [ConditionalFact(Skip = "Issue#16963")] public override void Can_build_monster_model_and_seed_data_using_dependent_navigations() { base.Can_build_monster_model_and_seed_data_using_dependent_navigations(); } - [ConditionalFact(Skip = "Include Issue#15711")] + [ConditionalFact(Skip = "Issue#16963")] public override void Can_build_monster_model_and_seed_data_using_FKs() { base.Can_build_monster_model_and_seed_data_using_FKs(); } - [ConditionalFact(Skip = "Include Issue#15711")] + [ConditionalFact(Skip = "Issue#16963")] public override void Can_build_monster_model_and_seed_data_using_navigations_with_deferred_add() { base.Can_build_monster_model_and_seed_data_using_navigations_with_deferred_add(); } - [ConditionalFact(Skip = "Include Issue#15711")] + [ConditionalFact(Skip = "Issue#16963")] public override void Can_build_monster_model_and_seed_data_using_principal_navigations() { base.Can_build_monster_model_and_seed_data_using_principal_navigations(); } - [ConditionalFact(Skip = "Include Issue#15711")] + [ConditionalFact(Skip = "Issue#16963")] public override void One_to_one_fixup_happens_when_FKs_change_test() { base.One_to_one_fixup_happens_when_FKs_change_test(); } - [ConditionalFact(Skip = "Include Issue#15711")] + [ConditionalFact(Skip = "Issue#16963")] public override void One_to_one_fixup_happens_when_reference_change_test() { base.One_to_one_fixup_happens_when_reference_change_test(); } - [ConditionalFact(Skip = "Include Issue#15711")] + [ConditionalFact(Skip = "Issue#16963")] public override void Composite_fixup_happens_when_FKs_change_test() { base.Composite_fixup_happens_when_FKs_change_test(); diff --git a/test/EFCore.InMemory.FunctionalTests/Query/AsyncGearsOfWarQueryInMemoryTest.cs b/test/EFCore.InMemory.FunctionalTests/Query/AsyncGearsOfWarQueryInMemoryTest.cs index 564449e3c3f..a82c81a088a 100644 --- a/test/EFCore.InMemory.FunctionalTests/Query/AsyncGearsOfWarQueryInMemoryTest.cs +++ b/test/EFCore.InMemory.FunctionalTests/Query/AsyncGearsOfWarQueryInMemoryTest.cs @@ -1,6 +1,8 @@ // 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.Threading.Tasks; +using Xunit; using Xunit.Abstractions; namespace Microsoft.EntityFrameworkCore.Query @@ -11,5 +13,11 @@ public AsyncGearsOfWarQueryInMemoryTest(GearsOfWarQueryInMemoryFixture fixture, : base(fixture) { } + + [ConditionalFact(Skip = "Issue#16963")] + public override Task GroupBy_Select_sum() + { + return base.GroupBy_Select_sum(); + } } } diff --git a/test/EFCore.InMemory.FunctionalTests/Query/AsyncSimpleQueryInMemoryTest.cs b/test/EFCore.InMemory.FunctionalTests/Query/AsyncSimpleQueryInMemoryTest.cs index 13f8693a0f2..85fadfb1e0a 100644 --- a/test/EFCore.InMemory.FunctionalTests/Query/AsyncSimpleQueryInMemoryTest.cs +++ b/test/EFCore.InMemory.FunctionalTests/Query/AsyncSimpleQueryInMemoryTest.cs @@ -14,19 +14,19 @@ public AsyncSimpleQueryInMemoryTest(NorthwindQueryInMemoryFixture Assert.Equal(e.Id, a.Id)); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_navigation_property_and_projection(bool isAsync) { @@ -1990,7 +1990,7 @@ public virtual Task SelectMany_navigation_property_and_projection(bool isAsync) l1s => l1s.SelectMany(l1 => l1.OneToMany_Optional1).Select(e => e.Name)); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_navigation_property_and_filter_before(bool isAsync) { @@ -2001,7 +2001,7 @@ public virtual Task SelectMany_navigation_property_and_filter_before(bool isAsyn (e, a) => Assert.Equal(e.Id, a.Id)); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_navigation_property_and_filter_after(bool isAsync) { @@ -2012,7 +2012,7 @@ public virtual Task SelectMany_navigation_property_and_filter_after(bool isAsync (e, a) => Assert.Equal(e.Id, a.Id)); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_nested_navigation_property_required(bool isAsync) { @@ -2027,7 +2027,7 @@ public virtual Task SelectMany_nested_navigation_property_required(bool isAsync) (e, a) => Assert.Equal(e.Id, a.Id)); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_nested_navigation_property_optional_and_projection(bool isAsync) { @@ -2040,7 +2040,7 @@ public virtual Task SelectMany_nested_navigation_property_optional_and_projectio () => l1.OneToOne_Optional_FK1.OneToMany_Optional2) ?? new List()).Select(e => e.Name)); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Multiple_SelectMany_calls(bool isAsync) { @@ -2051,7 +2051,7 @@ public virtual Task Multiple_SelectMany_calls(bool isAsync) (e, a) => Assert.Equal(e.Id, a.Id)); } - [ConditionalTheory(Skip = "issue #15081")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_navigation_property_with_another_navigation_in_subquery(bool isAsync) { @@ -2384,7 +2384,7 @@ public virtual Task Null_protection_logic_work_for_inner_key_access_of_manually_ (e, a) => Assert.Equal(e.Id, a.Id)); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory(Skip = "Issue#17068")] [MemberData(nameof(IsAsyncData))] public virtual Task Null_protection_logic_work_for_outer_key_access_of_manually_created_GroupJoin(bool isAsync) { @@ -2426,7 +2426,7 @@ public virtual Task Null_protection_logic_work_for_outer_key_access_of_manually_ }); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_where_with_subquery(bool isAsync) { @@ -2610,7 +2610,7 @@ public virtual Task Where_predicate_on_optional_reference_navigation(bool isAsyn .Select(l1 => l1.Name)); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_with_Include1(bool isAsync) { @@ -2643,7 +2643,7 @@ public virtual Task Orderby_SelectMany_with_Include1(bool isAsync) elementSorter: e => e.Id); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_with_Include2(bool isAsync) { @@ -2659,7 +2659,7 @@ public virtual Task SelectMany_with_Include2(bool isAsync) elementSorter: e => e.Id); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_with_Include_ThenInclude(bool isAsync) { @@ -2679,7 +2679,7 @@ public virtual Task SelectMany_with_Include_ThenInclude(bool isAsync) elementSorter: e => e.Id); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Multiple_SelectMany_with_Include(bool isAsync) { @@ -2700,7 +2700,7 @@ public virtual Task Multiple_SelectMany_with_Include(bool isAsync) elementSorter: e => e.Id); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_with_string_based_Include1(bool isAsync) { @@ -2716,7 +2716,7 @@ public virtual Task SelectMany_with_string_based_Include1(bool isAsync) elementSorter: e => e.Id); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_with_string_based_Include2(bool isAsync) { @@ -2735,7 +2735,7 @@ public virtual Task SelectMany_with_string_based_Include2(bool isAsync) elementSorter: e => e.Id); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Multiple_SelectMany_with_string_based_Include(bool isAsync) { @@ -2969,7 +2969,7 @@ public virtual Task Optional_navigation_with_Include_and_order(bool isAsync) assertOrder: true); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_with_order_by_and_Include(bool isAsync) { @@ -2989,7 +2989,7 @@ public virtual Task SelectMany_with_order_by_and_Include(bool isAsync) assertOrder: true); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_with_Include_and_order_by(bool isAsync) { @@ -3009,7 +3009,7 @@ public virtual Task SelectMany_with_Include_and_order_by(bool isAsync) assertOrder: true); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_with_navigation_and_explicit_DefaultIfEmpty(bool isAsync) { @@ -3041,7 +3041,7 @@ from l2 in l1.OneToMany_Optional1.Distinct() elementSorter: e => e.Id); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_with_navigation_filter_and_explicit_DefaultIfEmpty(bool isAsync) { @@ -3055,7 +3055,7 @@ from l2 in l1.OneToMany_Optional1.Where(l => l.Id > 5).DefaultIfEmpty() (e, a) => Assert.Equal(e.Id, a.Id)); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_with_nested_navigation_and_explicit_DefaultIfEmpty(bool isAsync) { @@ -3077,7 +3077,7 @@ from l3 in Maybe( (e, a) => Assert.Equal(e.Id, a.Id)); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_with_nested_navigation_filter_and_explicit_DefaultIfEmpty(bool isAsync) { @@ -3099,7 +3099,7 @@ from l3 in Maybe( (e, a) => Assert.Equal(e.Id, a.Id)); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_with_nested_required_navigation_filter_and_explicit_DefaultIfEmpty(bool isAsync) { @@ -3121,7 +3121,7 @@ from l3 in Maybe( (e, a) => Assert.Equal(e.Id, a.Id)); } - [ConditionalFact(Skip = "Issue#15711")] + [ConditionalFact] public virtual void SelectMany_with_nested_navigations_and_additional_joins_outside_of_SelectMany() { using (var ctx = CreateContext()) @@ -3138,7 +3138,7 @@ equals l2.Level1_Optional_Id } } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany( bool isAsync) @@ -3172,7 +3172,7 @@ l1.Id equals MaybeScalar(l2, () => l2.Level1_Optional_Id) }); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany2( bool isAsync) @@ -3202,7 +3202,7 @@ join l1 in l1s on MaybeScalar(l2, () => l2.Level1_Optional_Id) equals l1.Id }); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany3( bool isAsync) @@ -3231,7 +3231,7 @@ join l2 in l2s on MaybeScalar(l4, () => l4.Id) equals l2.Id }); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany4( bool isAsync) @@ -3262,7 +3262,7 @@ from l2 in grouping.DefaultIfEmpty() }); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Multiple_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_joined_together(bool isAsync) { @@ -3301,7 +3301,7 @@ join l2 in l4s.SelectMany( }); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_followed_by_Select_required_navigation_using_same_navs( @@ -3324,7 +3324,7 @@ select Maybe( () => l3.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2)); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_followed_by_Select_required_navigation_using_different_navs( @@ -3344,7 +3344,7 @@ select Maybe( () => l3.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2)); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Complex_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_with_other_query_operators_composed_on_top(bool isAsync) @@ -3430,7 +3430,7 @@ orderby MaybeScalar( }); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Multiple_SelectMany_with_navigation_and_explicit_DefaultIfEmpty(bool isAsync) { @@ -5340,7 +5340,7 @@ public virtual Task Accessing_optional_property_inside_result_operator_subquery( l1s => l1s.Where(l1 => names.All(n => Maybe(l1.OneToOne_Optional_FK1, () => l1.OneToOne_Optional_FK1.Name) != n))); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory(Skip = "Issue#16752")] [MemberData(nameof(IsAsyncData))] public virtual Task Include_after_SelectMany_and_reference_navigation(bool isAsync) { @@ -5354,7 +5354,7 @@ public virtual Task Include_after_SelectMany_and_reference_navigation(bool isAsy }); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory(Skip = "Issue#16752")] [MemberData(nameof(IsAsyncData))] public virtual Task Include_after_multiple_SelectMany_and_reference_navigation(bool isAsync) { @@ -5368,7 +5368,7 @@ public virtual Task Include_after_multiple_SelectMany_and_reference_navigation(b }); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory(Skip = "Issue#16752")] [MemberData(nameof(IsAsyncData))] public virtual Task Include_after_SelectMany_and_multiple_reference_navigations(bool isAsync) { @@ -5384,7 +5384,6 @@ public virtual Task Include_after_SelectMany_and_multiple_reference_navigations( }); } - // also #15081 [ConditionalTheory(Skip = "Issue #14935. Cannot eval 'Distinct()'")] [MemberData(nameof(IsAsyncData))] public virtual Task Include_after_SelectMany_and_reference_navigation_with_another_SelectMany_with_Distinct(bool isAsync) @@ -5407,7 +5406,7 @@ from lInner in lOuter.OneToMany_Optional3.Distinct() }); } - [ConditionalTheory(Skip = "issue #15081")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_subquery_with_custom_projection(bool isAsync) { @@ -5421,7 +5420,7 @@ public virtual Task SelectMany_subquery_with_custom_projection(bool isAsync) })).Take(1)); } - [ConditionalTheory(Skip = "issue #15081")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Null_check_in_anonymous_type_projection_should_not_be_removed(bool isAsync) { @@ -5478,7 +5477,7 @@ private class ProjectedDto public T Value { get; set; } } - [ConditionalTheory(Skip = "issue #15081")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_navigation_property_followed_by_select_collection_navigation(bool isAsync) { @@ -5494,7 +5493,7 @@ public virtual Task SelectMany_navigation_property_followed_by_select_collection }); } - [ConditionalTheory(Skip = "issue #15081")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Multiple_SelectMany_navigation_property_followed_by_select_collection_navigation(bool isAsync) { @@ -5511,7 +5510,7 @@ public virtual Task Multiple_SelectMany_navigation_property_followed_by_select_c }); } - [ConditionalFact(Skip = "issue #15081")] + [ConditionalFact] public virtual void SelectMany_navigation_property_with_include_and_followed_by_select_collection_navigation() { using (var ctx = CreateContext()) diff --git a/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs index a7d0a18df43..3e2b6c93364 100644 --- a/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs @@ -3651,7 +3651,7 @@ orderby f.Name } } - [ConditionalFact(Skip = "Issue#15711")] + [ConditionalFact] public virtual void Collection_navigation_access_on_derived_entity_using_cast() { using (var ctx = CreateContext()) @@ -3675,7 +3675,7 @@ orderby f.Name } } - [ConditionalFact(Skip = "Issue#15711")] + [ConditionalFact] public virtual void Collection_navigation_access_on_derived_entity_using_cast_in_SelectMany() { using (var ctx = CreateContext()) @@ -3806,7 +3806,7 @@ public virtual void Distinct_on_subquery_doesnt_get_lifted() } } - [ConditionalFact(Skip = "Issue#15711")] + [ConditionalFact] public virtual void Cast_result_operator_on_subquery_is_properly_lifted_to_a_convert() { using (var ctx = CreateContext()) @@ -3820,7 +3820,7 @@ public virtual void Cast_result_operator_on_subquery_is_properly_lifted_to_a_con } } - [ConditionalFact(Skip = "Issue#15711")] + [ConditionalFact] public virtual void Comparing_two_collection_navigations_composite_key() { using (var ctx = CreateContext()) @@ -3842,7 +3842,7 @@ orderby g1.Nickname } } - [ConditionalFact(Skip = "Issue#15711")] + [ConditionalFact(Skip = "Issue#17076")] public virtual void Comparing_two_collection_navigations_inheritance() { using (var ctx = CreateContext()) @@ -5436,7 +5436,7 @@ from o in gs.OfType() }); } - [ConditionalFact(Skip = "Issue#16330")] + [ConditionalFact] public virtual void Correlated_collection_with_top_level_FirstOrDefault() { using (var ctx = CreateContext()) @@ -5456,7 +5456,7 @@ public virtual void Correlated_collection_with_top_level_FirstOrDefault() } } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Correlated_collection_with_top_level_Count(bool isAsync) { @@ -5465,7 +5465,7 @@ public virtual Task Correlated_collection_with_top_level_Count(bool isAsync) gs => gs.Select(g => g.Weapons)); } - [ConditionalFact(Skip = "Issue#16330")] + [ConditionalFact] public virtual void Correlated_collection_with_top_level_Last_with_orderby_on_outer() { using (var ctx = CreateContext()) @@ -5486,7 +5486,7 @@ public virtual void Correlated_collection_with_top_level_Last_with_orderby_on_ou } } - [ConditionalFact(Skip = "Issue#16330")] + [ConditionalFact] public virtual void Correlated_collection_with_top_level_Last_with_order_by_on_inner() { using (var ctx = CreateContext()) @@ -5767,7 +5767,7 @@ join g in gs on o.FullName equals o.Nickname elementAsserter: (e, a) => CollectionAsserter(elementSorter: ee => ee)(e.Collection, a.Collection)); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory(Skip = "Issue#17068")] [MemberData(nameof(IsAsyncData))] public virtual Task Outer_parameter_in_group_join_key(bool isAsync) { @@ -6156,7 +6156,7 @@ public virtual void Include_with_group_by_on_entity_navigation_with_inheritance( } } - [ConditionalFact(Skip = "Issue#16330")] + [ConditionalFact(Skip = "Issue#16314")] public virtual void Streaming_correlated_collection_issue_11403() { Weapon[] expected; @@ -6542,7 +6542,7 @@ public virtual void Cast_to_derived_type_causes_client_eval() } } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Cast_to_derived_type_after_OfType_works(bool isAsync) { @@ -6931,7 +6931,7 @@ public virtual Task GroupBy_Property_Include_Select_Min(bool isAsync) gs => gs.Include(g => g.CityOfBirth).GroupBy(g => g.Rank).Select(g => g.Min(gg => gg.SquadId))); } - [ConditionalTheory(Skip = "Issue #15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task GroupBy_Property_Include_Aggregate_with_anonymous_selector(bool isAsync) { diff --git a/test/EFCore.Specification.Tests/Query/GroupByQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/GroupByQueryTestBase.cs index fd0f418e3de..191f4816440 100644 --- a/test/EFCore.Specification.Tests/Query/GroupByQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/GroupByQueryTestBase.cs @@ -1390,7 +1390,7 @@ public virtual Task Anonymous_projection_Distinct_GroupBy_Aggregate(bool isAsync e => e.Key); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_GroupBy_Aggregate(bool isAsync) { diff --git a/test/EFCore.Specification.Tests/Query/IncludeAsyncTestBase.cs b/test/EFCore.Specification.Tests/Query/IncludeAsyncTestBase.cs index fdf03a5f9ed..b702fa531e8 100644 --- a/test/EFCore.Specification.Tests/Query/IncludeAsyncTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/IncludeAsyncTestBase.cs @@ -319,7 +319,7 @@ join o in context.Set() on c.CustomerID equals o.CustomerID into g } } - [ConditionalFact(Skip = "issue #15711")] + [ConditionalFact(Skip = "Issue#17068")] public virtual async Task Include_collection_on_inner_group_join_clause_with_filter() { using (var context = CreateContext()) diff --git a/test/EFCore.Specification.Tests/Query/OwnedQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/OwnedQueryTestBase.cs index c512ae5ead5..d95f64b744f 100644 --- a/test/EFCore.Specification.Tests/Query/OwnedQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/OwnedQueryTestBase.cs @@ -140,7 +140,7 @@ public virtual void Query_when_group_by() } } - [ConditionalFact(Skip = "Issue#16330")] + [ConditionalFact] public virtual void Query_when_subquery() { using (var context = CreateContext()) @@ -230,7 +230,7 @@ public virtual void Navigation_rewrite_on_owned_collection_with_composition_comp } } - [ConditionalFact(Skip = "Issue#15711")] + [ConditionalFact] public virtual void SelectMany_on_owned_collection() { using (var ctx = CreateContext()) @@ -338,7 +338,7 @@ public virtual void Navigation_rewrite_on_owned_reference_followed_by_regular_en } } - [ConditionalFact(Skip = "Issue#15711")] + [ConditionalFact] public virtual void SelectMany_on_owned_reference_followed_by_regular_entity_and_collection() { using (var ctx = CreateContext()) @@ -351,7 +351,7 @@ public virtual void SelectMany_on_owned_reference_followed_by_regular_entity_and } } - [ConditionalFact(Skip = "Issue#15711")] + [ConditionalFact] public virtual void SelectMany_on_owned_reference_with_entity_in_between_ending_in_owned_collection() { using (var ctx = CreateContext()) diff --git a/test/EFCore.Specification.Tests/Query/QueryNavigationsTestBase.cs b/test/EFCore.Specification.Tests/Query/QueryNavigationsTestBase.cs index 8e782d6b838..51fbefdcb4d 100644 --- a/test/EFCore.Specification.Tests/Query/QueryNavigationsTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/QueryNavigationsTestBase.cs @@ -1383,9 +1383,8 @@ orderby c.CustomerID descending select grouping.Count()); } - [ConditionalTheory(Skip = "Issue#15711")] - [InlineData(false)] - //[InlineData(true)] issue #12449 + [ConditionalTheory(Skip = "Issue#17068")] + [MemberData(nameof(IsAsyncData))] public virtual Task Navigation_projection_on_groupjoin_qsre(bool isAsync) { return AssertQuery( @@ -1413,9 +1412,8 @@ join o in os on c.CustomerID equals o.CustomerID into grouping entryCount: 1); } - [ConditionalTheory(Skip = "Issue#15711")] - [InlineData(false)] - //[InlineData(true)] issue #12449 + [ConditionalTheory(Skip = "Issue#17068")] + [MemberData(nameof(IsAsyncData))] public virtual Task Navigation_projection_on_groupjoin_qsre_no_outer_in_final_result(bool isAsync) { return AssertQuery( @@ -1435,9 +1433,8 @@ select grouping.Select(o => o.OrderDetails).ToList(), }); } - [ConditionalTheory(Skip = "Issue#15711")] - [InlineData(false)] - //[InlineData(true)] issue #12449 + [ConditionalTheory(Skip = "Issue#17068")] + [MemberData(nameof(IsAsyncData))] public virtual Task Navigation_projection_on_groupjoin_qsre_with_empty_grouping(bool isAsync) { var anatrsOrders = new[] { 10308, 10625, 10759, 10926 }; @@ -1462,11 +1459,10 @@ where c.CustomerID.StartsWith("A") Assert.Equal(expected, actual); }, - // issue: #8956 entryCount: 4); } - [ConditionalFact(Skip = "Issue#15711")] + [ConditionalFact(Skip = "Issue#17068")] public virtual void Include_on_inner_projecting_groupjoin() { using (var ctx = CreateContext()) @@ -1485,7 +1481,7 @@ join o in ctx.Orders.Include(oo => oo.OrderDetails) on c.CustomerID equals o.Cus } } - [ConditionalFact(Skip = "Issue#15711")] + [ConditionalFact(Skip = "Issue#17068")] public virtual void Include_on_inner_projecting_groupjoin_complex() { using (var ctx = CreateContext()) diff --git a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.JoinGroupJoin.cs b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.JoinGroupJoin.cs index 625277046dd..24755c9f014 100644 --- a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.JoinGroupJoin.cs +++ b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.JoinGroupJoin.cs @@ -421,7 +421,7 @@ public virtual Task Join_same_collection_force_alias_uniquefication(bool isAsync entryCount: 830); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory(Skip = "Issue#17068")] [MemberData(nameof(IsAsyncData))] public virtual Task GroupJoin_customers_orders(bool isAsync) { @@ -588,7 +588,7 @@ from o in orders e => e.OrderID); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory(Skip = "Issue#17068")] [MemberData(nameof(IsAsyncData))] public virtual Task GroupJoin_tracking_groups(bool isAsync) { @@ -603,7 +603,7 @@ join o in os on c.CustomerID equals o.CustomerID into orders entryCount: 830); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory(Skip = "Issue#17068")] [MemberData(nameof(IsAsyncData))] public virtual Task GroupJoin_tracking_groups2(bool isAsync) { @@ -673,7 +673,7 @@ from o in orders entryCount: 919); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory(Skip = "Issue#17068")] [MemberData(nameof(IsAsyncData))] public virtual Task GroupJoin_outer_projection(bool isAsync) { @@ -694,7 +694,7 @@ public virtual Task GroupJoin_outer_projection(bool isAsync) entryCount: 830); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory(Skip = "Issue#17068")] [MemberData(nameof(IsAsyncData))] public virtual Task GroupJoin_outer_projection2(bool isAsync) { @@ -714,7 +714,7 @@ public virtual Task GroupJoin_outer_projection2(bool isAsync) }); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory(Skip = "Issue#17068")] [MemberData(nameof(IsAsyncData))] public virtual Task GroupJoin_outer_projection3(bool isAsync) { @@ -729,7 +729,7 @@ public virtual Task GroupJoin_outer_projection3(bool isAsync) elementAsserter: (e, a) => CollectionAsserter(s => s)(e.g, a.g)); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory(Skip = "Issue#17068")] [MemberData(nameof(IsAsyncData))] public virtual Task GroupJoin_outer_projection4(bool isAsync) { @@ -740,7 +740,7 @@ public virtual Task GroupJoin_outer_projection4(bool isAsync) elementAsserter: CollectionAsserter(s => s)); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory(Skip = "Issue#17068")] [MemberData(nameof(IsAsyncData))] public virtual Task GroupJoin_outer_projection_reverse(bool isAsync) { @@ -761,7 +761,7 @@ public virtual Task GroupJoin_outer_projection_reverse(bool isAsync) entryCount: 89); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory(Skip = "Issue#17068")] [MemberData(nameof(IsAsyncData))] public virtual Task GroupJoin_outer_projection_reverse2(bool isAsync) { diff --git a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.ResultOperators.cs b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.ResultOperators.cs index 4b71410b480..be61d8d2524 100644 --- a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.ResultOperators.cs +++ b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.ResultOperators.cs @@ -1476,7 +1476,7 @@ await AssertQuery( }))); } - [ConditionalFact(Skip = "Issue#15711")] + [ConditionalFact] public virtual void OfType_Select() { using (var context = CreateContext()) @@ -1491,7 +1491,7 @@ public virtual void OfType_Select() } } - [ConditionalFact(Skip = "Issue#15711")] + [ConditionalFact] public virtual void OfType_Select_OfType_Select() { using (var context = CreateContext()) diff --git a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.Select.cs b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.Select.cs index 1036067e8c0..d00d85b6226 100644 --- a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.Select.cs +++ b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.Select.cs @@ -1200,6 +1200,8 @@ public virtual Task Client_method_in_projection_requiring_materialization_2(bool entryCount: 4); } + private static string ClientMethod(Customer c) => c.CustomerID; + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Projecting_nullable_struct(bool isAsync) @@ -1221,6 +1223,37 @@ public struct MyStruct public int X, Y; } - private static string ClientMethod(Customer c) => c.CustomerID; + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Multiple_select_many_with_predicate(bool isAsync) + { + return AssertQuery( + isAsync, + cs => from c in cs + from o in c.Orders + from od in o.OrderDetails + where od.Discount >= 0.25 + select c, + entryCount: 38); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task SelectMany_without_result_selector_naked_collection_navigation(bool isAsync) + { + return AssertQuery( + isAsync, + cs => cs.SelectMany(c => c.Orders), + entryCount: 830); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task SelectMany_without_result_selector_collection_navigation_composed(bool isAsync) + { + return AssertQuery( + isAsync, + cs => cs.SelectMany(c => c.Orders.Select(o => o.CustomerID))); + } } } diff --git a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs index 2737d5401ae..c7eb6a3150e 100644 --- a/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/SimpleQueryTestBase.cs @@ -496,7 +496,8 @@ public virtual Task Entity_equality_through_nested_anonymous_type_projection(boo o => o .Select(x => new { - CustomerInfo = new { + CustomerInfo = new + { x.Customer } }) @@ -1721,7 +1722,7 @@ public virtual void Select_nested_collection_count_using_DTO() } } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Select_DTO_with_member_init_distinct_in_subquery_translated_to_server(bool isAsync) { @@ -1741,6 +1742,26 @@ from c in cs.Where(c => c.CustomerID == o.Id) entryCount: 35); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Select_DTO_with_member_init_distinct_in_subquery_translated_to_server_2(bool isAsync) + { + return AssertQuery( + isAsync, + (cs, os) => + from o in os.Where(o => o.OrderID < 10300) + .Select( + o => new OrderCountDTO + { + Id = o.CustomerID, + Count = o.OrderID + }) + .Distinct() + from c in cs.Where(c => o.Id == c.CustomerID) + select c, + entryCount: 35); + } + [ConditionalFact] public virtual void Select_DTO_with_member_init_distinct_in_subquery_used_in_projection_translated_to_server() { @@ -2397,7 +2418,7 @@ from e in es entryCount: 15); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_correlated_subquery_simple(bool isAsync) { @@ -2663,7 +2684,7 @@ private class Foo protected const uint NonExistentID = uint.MaxValue; - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Default_if_empty_top_level(bool isAsync) { @@ -2674,9 +2695,8 @@ from e in es.Where(c => c.EmployeeID == NonExistentID).DefaultIfEmpty() select e); } - // issue #12872 - //[ConditionalTheory] - //[MemberData(nameof(IsAsyncData))] + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] public virtual Task Join_with_default_if_empty_on_both_sources(bool isAsync) { return AssertQuery( @@ -2688,9 +2708,8 @@ from e in es.Where(c => c.EmployeeID == NonExistentID).DefaultIfEmpty() select e, o => o, i => i, (o, i) => o)); } - // issue #12567 - //[ConditionalTheory] - //[MemberData(nameof(IsAsyncData))] + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] public virtual Task Default_if_empty_top_level_followed_by_projecting_constant(bool isAsync) { return AssertQuery( @@ -2712,9 +2731,8 @@ from e in es.Where(c => c.EmployeeID == NonExistentID).DefaultIfEmpty(new Employ entryCount: 1); } - // issue #12572 - //[ConditionalTheory] - //[MemberData(nameof(IsAsyncData))] + [ConditionalTheory(Skip = "Issue #14935. Cannot eval 'DefaultIfEmpty(__p_0)'")] + [MemberData(nameof(IsAsyncData))] public virtual Task Default_if_empty_top_level_arg_followed_by_projecting_constant(bool isAsync) { return AssertQueryScalar( @@ -2724,7 +2742,7 @@ from e in es.Where(c => c.EmployeeID == NonExistentID).DefaultIfEmpty(new Employ select 42); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Default_if_empty_top_level_positive(bool isAsync) { @@ -2736,7 +2754,7 @@ from e in es.Where(c => c.EmployeeID > 0).DefaultIfEmpty() entryCount: 9); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Default_if_empty_top_level_projection(bool isAsync) { @@ -3205,7 +3223,7 @@ public virtual void OrderBy_any() } } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_Joined(bool isAsync) { @@ -3222,7 +3240,7 @@ from o in os.Where(o => o.CustomerID == c.CustomerID) e => e.ContactName + " " + e.OrderDate); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_Joined_DefaultIfEmpty(bool isAsync) { @@ -3240,7 +3258,7 @@ from o in os.Where(o => o.CustomerID == c.CustomerID).DefaultIfEmpty() entryCount: 830); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_Joined_Take(bool isAsync) { @@ -3258,7 +3276,7 @@ from o in os.Where(o => o.CustomerID == c.CustomerID).Take(1000) entryCount: 830); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task SelectMany_Joined_DefaultIfEmpty2(bool isAsync) { @@ -3272,7 +3290,7 @@ from o in os.Where(o => o.CustomerID == c.CustomerID).DefaultIfEmpty() entryCount: 830); } - [ConditionalTheory(Skip = "Issue #15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Select_many_cross_join_same_collection(bool isAsync) { @@ -4466,7 +4484,7 @@ public virtual Task Select_expression_references_are_updated_correctly_with_subq .Where(x => x < nextYear)); } - [ConditionalFact(Skip = "Issue#15711")] + [ConditionalFact] public virtual void DefaultIfEmpty_without_group_join() { using (var context = CreateContext()) @@ -4482,7 +4500,7 @@ public virtual void DefaultIfEmpty_without_group_join() } } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task DefaultIfEmpty_in_subquery(bool isAsync) { @@ -4500,7 +4518,24 @@ from o in os.Where(o => o.CustomerID == c.CustomerID).DefaultIfEmpty() e => e.CustomerID + " " + e.OrderID); } - [ConditionalTheory(Skip = "Issue#15711")] + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task DefaultIfEmpty_in_subquery_not_correlated(bool isAsync) + { + return AssertQuery( + isAsync, + (cs, os) => + (from c in cs + from o in os.Where(o => o.OrderID > 15000).DefaultIfEmpty() + select new + { + c.CustomerID, + OrderID = o != null ? o.OrderID : (int?)null + }), + e => e.CustomerID + " " + e.OrderID); + } + + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task DefaultIfEmpty_in_subquery_nested(bool isAsync) { @@ -4508,7 +4543,7 @@ public virtual Task DefaultIfEmpty_in_subquery_nested(bool isAsync) isAsync, (cs, os) => (from c in cs.Where(c => c.City == "Seattle") - from o1 in os.Where(o => o.OrderID > 11000).DefaultIfEmpty() + from o1 in os.Where(o => o.OrderID > 15000).DefaultIfEmpty() from o2 in os.Where(o => o.CustomerID == c.CustomerID).DefaultIfEmpty() where o1 != null && o2 != null orderby o1.OrderID, o2.OrderDate @@ -4696,8 +4731,7 @@ from e2 in grouping.DefaultIfEmpty() } [ConditionalTheory(Skip = "Issue #14935. Cannot eval 'from Customer c in ClientDefaultIfEmpty([grouping])'")] - [InlineData(false)] - //[InlineData(true)] issue #12449 + [MemberData(nameof(IsAsyncData))] public virtual Task No_orderby_added_for_client_side_GroupJoin_dependent_to_principal_LOJ(bool isAsync) { return AssertQuery( @@ -4717,8 +4751,7 @@ from c in ClientDefaultIfEmpty(grouping) } [ConditionalTheory(Skip = "Issue #14935. Cannot eval 'from Customer c in ClientDefaultIfEmpty([grouping])'")] - [InlineData(false)] - //[InlineData(true)] issue #12449 + [MemberData(nameof(IsAsyncData))] public virtual Task No_orderby_added_for_client_side_GroupJoin_dependent_to_principal_LOJ_with_additional_join_condition1( bool isAsync) { @@ -4747,8 +4780,7 @@ from c in ClientDefaultIfEmpty(grouping) } [ConditionalTheory(Skip = "Issue #14935. Cannot eval 'from Customer c in ClientDefaultIfEmpty([grouping])'")] - [InlineData(false)] - //[InlineData(true)] issue #12449 + [MemberData(nameof(IsAsyncData))] public virtual Task No_orderby_added_for_client_side_GroupJoin_dependent_to_principal_LOJ_with_additional_join_condition2( bool isAsync) { @@ -4777,8 +4809,7 @@ from c in ClientDefaultIfEmpty(grouping) } [ConditionalTheory(Skip = "Issue #14935. Cannot eval 'from Employee e2 in ClientDefaultIfEmpty([grouping])'")] - [InlineData(false)] - //[InlineData(true)] issue #12449 + [MemberData(nameof(IsAsyncData))] public virtual Task Orderby_added_for_client_side_GroupJoin_principal_to_dependent_LOJ(bool isAsync) { return AssertQuery( diff --git a/test/EFCore.Specification.Tests/TestUtilities/QueryTestGeneration/ProceduralQueryExpressionGenerator.cs b/test/EFCore.Specification.Tests/TestUtilities/QueryTestGeneration/ProceduralQueryExpressionGenerator.cs index 39b3ede927f..b9177bb05ca 100644 --- a/test/EFCore.Specification.Tests/TestUtilities/QueryTestGeneration/ProceduralQueryExpressionGenerator.cs +++ b/test/EFCore.Specification.Tests/TestUtilities/QueryTestGeneration/ProceduralQueryExpressionGenerator.cs @@ -123,10 +123,6 @@ static ProcedurallyGeneratedQueryExecutor() // -------------------------------------------------------------- actual product bugs -------------------------------------------------------------- - AddExpectedFailure("Default_if_empty_top_level", "Object reference not set to an instance of an object."); // 12567 - AddExpectedFailure("Default_if_empty_top_level_positive", "Object reference not set to an instance of an object."); // 12567 - AddExpectedFailure("Default_if_empty_top_level_projection", "Object reference not set to an instance of an object."); // 12567 - AddExpectedFailure("Except_simple", "cannot be used for"); // 12568 AddExpectedFailure("Except_dbset", "cannot be used for"); // 12568 AddExpectedFailure("Except_nested", "cannot be used for"); // 12568 @@ -134,10 +130,6 @@ static ProcedurallyGeneratedQueryExecutor() AddExpectedFailure("GroupBy_aggregate_Pushdown", "Invalid column name 'c'."); // 12569 AddExpectedFailure("GroupBy_with_orderby_take_skip_distinct", "Invalid column name 'c'."); // 12569 - AddExpectedFailure( - "Default_if_empty_top_level_arg", - "Expression of type 'Microsoft.EntityFrameworkCore.TestModels.Northwind.Employee' cannot be used for parameter of type"); // 12572 - AddExpectedFailure( "GroupBy_Select_First_GroupBy", "Query source (from Customer c in [g]) has already been associated with an expression."); // 12573 @@ -401,10 +393,6 @@ static ProcedurallyGeneratedQueryExecutor() "Where_poco_closure", "has already been declared. Variable names must be unique within a query batch or stored procedure."); // 12871 - AddExpectedFailure( - "Default_if_empty_top_level_positive", "Operation is not valid due to the current state of the object."); // 12872 - AddExpectedFailure("Default_if_empty_top_level", "Operation is not valid due to the current state of the object."); // 12872 - AddExpectedFailure("QueryType_with_defining_query", "Object reference not set to an instance of an object."); // 12873 AddExpectedFailure( diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServerTest.cs index 73d9b92b33e..e9e730277f4 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsQuerySqlServerTest.cs @@ -1221,82 +1221,75 @@ public override async Task SelectMany_navigation_property(bool isAsync) { await base.SelectMany_navigation_property(isAsync); - // issue #15081 -// AssertSql( -// @"SELECT [l1.OneToMany_Optional1].[Id], [l1.OneToMany_Optional1].[Date], [l1.OneToMany_Optional1].[Level1_Optional_Id], [l1.OneToMany_Optional1].[Level1_Required_Id], [l1.OneToMany_Optional1].[Name], [l1.OneToMany_Optional1].[OneToMany_Optional_Inverse2Id], [l1.OneToMany_Optional1].[OneToMany_Optional_Self_Inverse2Id], [l1.OneToMany_Optional1].[OneToMany_Required_Inverse2Id], [l1.OneToMany_Optional1].[OneToMany_Required_Self_Inverse2Id], [l1.OneToMany_Optional1].[OneToOne_Optional_PK_Inverse2Id], [l1.OneToMany_Optional1].[OneToOne_Optional_Self2Id] -//FROM [LevelOne] AS [l1] -//INNER JOIN [LevelTwo] AS [l1.OneToMany_Optional1] ON [l1].[Id] = [l1.OneToMany_Optional1].[OneToMany_Optional_Inverse2Id]"); + AssertSql( + @"SELECT [l1.OneToMany_Optional1].[Id], [l1.OneToMany_Optional1].[Date], [l1.OneToMany_Optional1].[Level1_Optional_Id], [l1.OneToMany_Optional1].[Level1_Required_Id], [l1.OneToMany_Optional1].[Name], [l1.OneToMany_Optional1].[OneToMany_Optional_Inverse2Id], [l1.OneToMany_Optional1].[OneToMany_Optional_Self_Inverse2Id], [l1.OneToMany_Optional1].[OneToMany_Required_Inverse2Id], [l1.OneToMany_Optional1].[OneToMany_Required_Self_Inverse2Id], [l1.OneToMany_Optional1].[OneToOne_Optional_PK_Inverse2Id], [l1.OneToMany_Optional1].[OneToOne_Optional_Self2Id] +FROM [LevelOne] AS [l1] +INNER JOIN [LevelTwo] AS [l1.OneToMany_Optional1] ON [l1].[Id] = [l1.OneToMany_Optional1].[OneToMany_Optional_Inverse2Id]"); } public override async Task SelectMany_navigation_property_and_projection(bool isAsync) { await base.SelectMany_navigation_property_and_projection(isAsync); - // issue #15081 -// AssertSql( -// @"SELECT [l1.OneToMany_Optional1].[Name] -//FROM [LevelOne] AS [l1] -//INNER JOIN [LevelTwo] AS [l1.OneToMany_Optional1] ON [l1].[Id] = [l1.OneToMany_Optional1].[OneToMany_Optional_Inverse2Id]"); + AssertSql( + @"SELECT [l1.OneToMany_Optional1].[Name] +FROM [LevelOne] AS [l1] +INNER JOIN [LevelTwo] AS [l1.OneToMany_Optional1] ON [l1].[Id] = [l1.OneToMany_Optional1].[OneToMany_Optional_Inverse2Id]"); } public override async Task SelectMany_navigation_property_and_filter_before(bool isAsync) { await base.SelectMany_navigation_property_and_filter_before(isAsync); - // issue #15081 -// AssertSql( -// @"SELECT [e.OneToMany_Optional1].[Id], [e.OneToMany_Optional1].[Date], [e.OneToMany_Optional1].[Level1_Optional_Id], [e.OneToMany_Optional1].[Level1_Required_Id], [e.OneToMany_Optional1].[Name], [e.OneToMany_Optional1].[OneToMany_Optional_Inverse2Id], [e.OneToMany_Optional1].[OneToMany_Optional_Self_Inverse2Id], [e.OneToMany_Optional1].[OneToMany_Required_Inverse2Id], [e.OneToMany_Optional1].[OneToMany_Required_Self_Inverse2Id], [e.OneToMany_Optional1].[OneToOne_Optional_PK_Inverse2Id], [e.OneToMany_Optional1].[OneToOne_Optional_Self2Id] -//FROM [LevelOne] AS [e] -//INNER JOIN [LevelTwo] AS [e.OneToMany_Optional1] ON [e].[Id] = [e.OneToMany_Optional1].[OneToMany_Optional_Inverse2Id] -//WHERE [e].[Id] = 1"); + AssertSql( + @"SELECT [e.OneToMany_Optional1].[Id], [e.OneToMany_Optional1].[Date], [e.OneToMany_Optional1].[Level1_Optional_Id], [e.OneToMany_Optional1].[Level1_Required_Id], [e.OneToMany_Optional1].[Name], [e.OneToMany_Optional1].[OneToMany_Optional_Inverse2Id], [e.OneToMany_Optional1].[OneToMany_Optional_Self_Inverse2Id], [e.OneToMany_Optional1].[OneToMany_Required_Inverse2Id], [e.OneToMany_Optional1].[OneToMany_Required_Self_Inverse2Id], [e.OneToMany_Optional1].[OneToOne_Optional_PK_Inverse2Id], [e.OneToMany_Optional1].[OneToOne_Optional_Self2Id] +FROM [LevelOne] AS [e] +INNER JOIN [LevelTwo] AS [e.OneToMany_Optional1] ON [e].[Id] = [e.OneToMany_Optional1].[OneToMany_Optional_Inverse2Id] +WHERE [e].[Id] = 1"); } public override async Task SelectMany_navigation_property_and_filter_after(bool isAsync) { await base.SelectMany_navigation_property_and_filter_after(isAsync); - // issue #15081 -// AssertSql( -// @"SELECT [l1.OneToMany_Optional1].[Id], [l1.OneToMany_Optional1].[Date], [l1.OneToMany_Optional1].[Level1_Optional_Id], [l1.OneToMany_Optional1].[Level1_Required_Id], [l1.OneToMany_Optional1].[Name], [l1.OneToMany_Optional1].[OneToMany_Optional_Inverse2Id], [l1.OneToMany_Optional1].[OneToMany_Optional_Self_Inverse2Id], [l1.OneToMany_Optional1].[OneToMany_Required_Inverse2Id], [l1.OneToMany_Optional1].[OneToMany_Required_Self_Inverse2Id], [l1.OneToMany_Optional1].[OneToOne_Optional_PK_Inverse2Id], [l1.OneToMany_Optional1].[OneToOne_Optional_Self2Id] -//FROM [LevelOne] AS [l1] -//INNER JOIN [LevelTwo] AS [l1.OneToMany_Optional1] ON [l1].[Id] = [l1.OneToMany_Optional1].[OneToMany_Optional_Inverse2Id] -//WHERE [l1.OneToMany_Optional1].[Id] <> 6"); + AssertSql( + @"SELECT [l1.OneToMany_Optional1].[Id], [l1.OneToMany_Optional1].[Date], [l1.OneToMany_Optional1].[Level1_Optional_Id], [l1.OneToMany_Optional1].[Level1_Required_Id], [l1.OneToMany_Optional1].[Name], [l1.OneToMany_Optional1].[OneToMany_Optional_Inverse2Id], [l1.OneToMany_Optional1].[OneToMany_Optional_Self_Inverse2Id], [l1.OneToMany_Optional1].[OneToMany_Required_Inverse2Id], [l1.OneToMany_Optional1].[OneToMany_Required_Self_Inverse2Id], [l1.OneToMany_Optional1].[OneToOne_Optional_PK_Inverse2Id], [l1.OneToMany_Optional1].[OneToOne_Optional_Self2Id] +FROM [LevelOne] AS [l1] +INNER JOIN [LevelTwo] AS [l1.OneToMany_Optional1] ON [l1].[Id] = [l1.OneToMany_Optional1].[OneToMany_Optional_Inverse2Id] +WHERE [l1.OneToMany_Optional1].[Id] <> 6"); } public override async Task SelectMany_nested_navigation_property_required(bool isAsync) { await base.SelectMany_nested_navigation_property_required(isAsync); - // issue #15081 -// AssertSql( -// @"SELECT [l1.OneToOne_Required_FK1.OneToMany_Optional2].[Id], [l1.OneToOne_Required_FK1.OneToMany_Optional2].[Level2_Optional_Id], [l1.OneToOne_Required_FK1.OneToMany_Optional2].[Level2_Required_Id], [l1.OneToOne_Required_FK1.OneToMany_Optional2].[Name], [l1.OneToOne_Required_FK1.OneToMany_Optional2].[OneToMany_Optional_Inverse3Id], [l1.OneToOne_Required_FK1.OneToMany_Optional2].[OneToMany_Optional_Self_Inverse3Id], [l1.OneToOne_Required_FK1.OneToMany_Optional2].[OneToMany_Required_Inverse3Id], [l1.OneToOne_Required_FK1.OneToMany_Optional2].[OneToMany_Required_Self_Inverse3Id], [l1.OneToOne_Required_FK1.OneToMany_Optional2].[OneToOne_Optional_PK_Inverse3Id], [l1.OneToOne_Required_FK1.OneToMany_Optional2].[OneToOne_Optional_Self3Id] -//FROM [LevelOne] AS [l1] -//INNER JOIN [LevelTwo] AS [l1.OneToOne_Required_FK1] ON [l1].[Id] = [l1.OneToOne_Required_FK1].[Level1_Required_Id] -//INNER JOIN [LevelThree] AS [l1.OneToOne_Required_FK1.OneToMany_Optional2] ON [l1.OneToOne_Required_FK1].[Id] = [l1.OneToOne_Required_FK1.OneToMany_Optional2].[OneToMany_Optional_Inverse3Id]"); + AssertSql( + @"SELECT [l1.OneToOne_Required_FK1.OneToMany_Optional2].[Id], [l1.OneToOne_Required_FK1.OneToMany_Optional2].[Level2_Optional_Id], [l1.OneToOne_Required_FK1.OneToMany_Optional2].[Level2_Required_Id], [l1.OneToOne_Required_FK1.OneToMany_Optional2].[Name], [l1.OneToOne_Required_FK1.OneToMany_Optional2].[OneToMany_Optional_Inverse3Id], [l1.OneToOne_Required_FK1.OneToMany_Optional2].[OneToMany_Optional_Self_Inverse3Id], [l1.OneToOne_Required_FK1.OneToMany_Optional2].[OneToMany_Required_Inverse3Id], [l1.OneToOne_Required_FK1.OneToMany_Optional2].[OneToMany_Required_Self_Inverse3Id], [l1.OneToOne_Required_FK1.OneToMany_Optional2].[OneToOne_Optional_PK_Inverse3Id], [l1.OneToOne_Required_FK1.OneToMany_Optional2].[OneToOne_Optional_Self3Id] +FROM [LevelOne] AS [l1] +INNER JOIN [LevelTwo] AS [l1.OneToOne_Required_FK1] ON [l1].[Id] = [l1.OneToOne_Required_FK1].[Level1_Required_Id] +INNER JOIN [LevelThree] AS [l1.OneToOne_Required_FK1.OneToMany_Optional2] ON [l1.OneToOne_Required_FK1].[Id] = [l1.OneToOne_Required_FK1.OneToMany_Optional2].[OneToMany_Optional_Inverse3Id]"); } public override async Task SelectMany_nested_navigation_property_optional_and_projection(bool isAsync) { await base.SelectMany_nested_navigation_property_optional_and_projection(isAsync); - // issue #15081 -// AssertSql( -// @"SELECT [l1.OneToOne_Optional_FK1.OneToMany_Optional2].[Name] -//FROM [LevelOne] AS [l1] -//INNER JOIN [LevelTwo] AS [l1.OneToOne_Optional_FK1] ON [l1].[Id] = [l1.OneToOne_Optional_FK1].[Level1_Optional_Id] -//INNER JOIN [LevelThree] AS [l1.OneToOne_Optional_FK1.OneToMany_Optional2] ON [l1.OneToOne_Optional_FK1].[Id] = [l1.OneToOne_Optional_FK1.OneToMany_Optional2].[OneToMany_Optional_Inverse3Id]"); + AssertSql( + @"SELECT [l1.OneToOne_Optional_FK1.OneToMany_Optional2].[Name] +FROM [LevelOne] AS [l1] +INNER JOIN [LevelTwo] AS [l1.OneToOne_Optional_FK1] ON [l1].[Id] = [l1.OneToOne_Optional_FK1].[Level1_Optional_Id] +INNER JOIN [LevelThree] AS [l1.OneToOne_Optional_FK1.OneToMany_Optional2] ON [l1.OneToOne_Optional_FK1].[Id] = [l1.OneToOne_Optional_FK1.OneToMany_Optional2].[OneToMany_Optional_Inverse3Id]"); } public override async Task Multiple_SelectMany_calls(bool isAsync) { await base.Multiple_SelectMany_calls(isAsync); - // issue #15081 -// AssertSql( -// @"SELECT [e.OneToMany_Optional1.OneToMany_Optional2].[Id], [e.OneToMany_Optional1.OneToMany_Optional2].[Level2_Optional_Id], [e.OneToMany_Optional1.OneToMany_Optional2].[Level2_Required_Id], [e.OneToMany_Optional1.OneToMany_Optional2].[Name], [e.OneToMany_Optional1.OneToMany_Optional2].[OneToMany_Optional_Inverse3Id], [e.OneToMany_Optional1.OneToMany_Optional2].[OneToMany_Optional_Self_Inverse3Id], [e.OneToMany_Optional1.OneToMany_Optional2].[OneToMany_Required_Inverse3Id], [e.OneToMany_Optional1.OneToMany_Optional2].[OneToMany_Required_Self_Inverse3Id], [e.OneToMany_Optional1.OneToMany_Optional2].[OneToOne_Optional_PK_Inverse3Id], [e.OneToMany_Optional1.OneToMany_Optional2].[OneToOne_Optional_Self3Id] -//FROM [LevelOne] AS [e] -//INNER JOIN [LevelTwo] AS [e.OneToMany_Optional1] ON [e].[Id] = [e.OneToMany_Optional1].[OneToMany_Optional_Inverse2Id] -//INNER JOIN [LevelThree] AS [e.OneToMany_Optional1.OneToMany_Optional2] ON [e.OneToMany_Optional1].[Id] = [e.OneToMany_Optional1.OneToMany_Optional2].[OneToMany_Optional_Inverse3Id]"); + AssertSql( + @"SELECT [e.OneToMany_Optional1.OneToMany_Optional2].[Id], [e.OneToMany_Optional1.OneToMany_Optional2].[Level2_Optional_Id], [e.OneToMany_Optional1.OneToMany_Optional2].[Level2_Required_Id], [e.OneToMany_Optional1.OneToMany_Optional2].[Name], [e.OneToMany_Optional1.OneToMany_Optional2].[OneToMany_Optional_Inverse3Id], [e.OneToMany_Optional1.OneToMany_Optional2].[OneToMany_Optional_Self_Inverse3Id], [e.OneToMany_Optional1.OneToMany_Optional2].[OneToMany_Required_Inverse3Id], [e.OneToMany_Optional1.OneToMany_Optional2].[OneToMany_Required_Self_Inverse3Id], [e.OneToMany_Optional1.OneToMany_Optional2].[OneToOne_Optional_PK_Inverse3Id], [e.OneToMany_Optional1.OneToMany_Optional2].[OneToOne_Optional_Self3Id] +FROM [LevelOne] AS [e] +INNER JOIN [LevelTwo] AS [e.OneToMany_Optional1] ON [e].[Id] = [e.OneToMany_Optional1].[OneToMany_Optional_Inverse2Id] +INNER JOIN [LevelThree] AS [e.OneToMany_Optional1.OneToMany_Optional2] ON [e.OneToMany_Optional1].[Id] = [e.OneToMany_Optional1.OneToMany_Optional2].[OneToMany_Optional_Inverse3Id]"); } public override async Task SelectMany_navigation_property_with_another_navigation_in_subquery(bool isAsync) @@ -1699,15 +1692,14 @@ public override async Task SelectMany_where_with_subquery(bool isAsync) { await base.SelectMany_where_with_subquery(isAsync); - // issue #15081 -// AssertSql( -// @"SELECT [l1.OneToMany_Required1].[Id], [l1.OneToMany_Required1].[Date], [l1.OneToMany_Required1].[Level1_Optional_Id], [l1.OneToMany_Required1].[Level1_Required_Id], [l1.OneToMany_Required1].[Name], [l1.OneToMany_Required1].[OneToMany_Optional_Inverse2Id], [l1.OneToMany_Required1].[OneToMany_Optional_Self_Inverse2Id], [l1.OneToMany_Required1].[OneToMany_Required_Inverse2Id], [l1.OneToMany_Required1].[OneToMany_Required_Self_Inverse2Id], [l1.OneToMany_Required1].[OneToOne_Optional_PK_Inverse2Id], [l1.OneToMany_Required1].[OneToOne_Optional_Self2Id] -//FROM [LevelOne] AS [l1] -//INNER JOIN [LevelTwo] AS [l1.OneToMany_Required1] ON [l1].[Id] = [l1.OneToMany_Required1].[OneToMany_Required_Inverse2Id] -//WHERE EXISTS ( -// SELECT 1 -// FROM [LevelThree] AS [l] -// WHERE [l1.OneToMany_Required1].[Id] = [l].[OneToMany_Required_Inverse3Id])"); + AssertSql( + @"SELECT [l1.OneToMany_Required1].[Id], [l1.OneToMany_Required1].[Date], [l1.OneToMany_Required1].[Level1_Optional_Id], [l1.OneToMany_Required1].[Level1_Required_Id], [l1.OneToMany_Required1].[Name], [l1.OneToMany_Required1].[OneToMany_Optional_Inverse2Id], [l1.OneToMany_Required1].[OneToMany_Optional_Self_Inverse2Id], [l1.OneToMany_Required1].[OneToMany_Required_Inverse2Id], [l1.OneToMany_Required1].[OneToMany_Required_Self_Inverse2Id], [l1.OneToMany_Required1].[OneToOne_Optional_PK_Inverse2Id], [l1.OneToMany_Required1].[OneToOne_Optional_Self2Id] +FROM [LevelOne] AS [l1] +INNER JOIN [LevelTwo] AS [l1.OneToMany_Required1] ON [l1].[Id] = [l1.OneToMany_Required1].[OneToMany_Required_Inverse2Id] +WHERE EXISTS ( + SELECT 1 + FROM [LevelThree] AS [l] + WHERE [l1.OneToMany_Required1].[Id] = [l].[OneToMany_Required_Inverse3Id])"); } public override async Task Order_by_key_of_projected_navigation_doesnt_get_optimized_into_FK_access1(bool isAsync) @@ -1864,19 +1856,11 @@ public override async Task SelectMany_with_Include1(bool isAsync) await base.SelectMany_with_Include1(isAsync); AssertSql( - @"SELECT [l1.OneToMany_Optional1].[Id], [l1.OneToMany_Optional1].[Date], [l1.OneToMany_Optional1].[Level1_Optional_Id], [l1.OneToMany_Optional1].[Level1_Required_Id], [l1.OneToMany_Optional1].[Name], [l1.OneToMany_Optional1].[OneToMany_Optional_Inverse2Id], [l1.OneToMany_Optional1].[OneToMany_Optional_Self_Inverse2Id], [l1.OneToMany_Optional1].[OneToMany_Required_Inverse2Id], [l1.OneToMany_Optional1].[OneToMany_Required_Self_Inverse2Id], [l1.OneToMany_Optional1].[OneToOne_Optional_PK_Inverse2Id], [l1.OneToMany_Optional1].[OneToOne_Optional_Self2Id] -FROM [LevelOne] AS [l1] -INNER JOIN [LevelTwo] AS [l1.OneToMany_Optional1] ON [l1].[Id] = [l1.OneToMany_Optional1].[OneToMany_Optional_Inverse2Id] -ORDER BY [l1.OneToMany_Optional1].[Id]", - // - @"SELECT [l1.OneToMany_Optional1.OneToMany_Optional2].[Id], [l1.OneToMany_Optional1.OneToMany_Optional2].[Level2_Optional_Id], [l1.OneToMany_Optional1.OneToMany_Optional2].[Level2_Required_Id], [l1.OneToMany_Optional1.OneToMany_Optional2].[Name], [l1.OneToMany_Optional1.OneToMany_Optional2].[OneToMany_Optional_Inverse3Id], [l1.OneToMany_Optional1.OneToMany_Optional2].[OneToMany_Optional_Self_Inverse3Id], [l1.OneToMany_Optional1.OneToMany_Optional2].[OneToMany_Required_Inverse3Id], [l1.OneToMany_Optional1.OneToMany_Optional2].[OneToMany_Required_Self_Inverse3Id], [l1.OneToMany_Optional1.OneToMany_Optional2].[OneToOne_Optional_PK_Inverse3Id], [l1.OneToMany_Optional1.OneToMany_Optional2].[OneToOne_Optional_Self3Id] -FROM [LevelThree] AS [l1.OneToMany_Optional1.OneToMany_Optional2] -INNER JOIN ( - SELECT DISTINCT [l1.OneToMany_Optional10].[Id] - FROM [LevelOne] AS [l10] - INNER JOIN [LevelTwo] AS [l1.OneToMany_Optional10] ON [l10].[Id] = [l1.OneToMany_Optional10].[OneToMany_Optional_Inverse2Id] -) AS [t] ON [l1.OneToMany_Optional1.OneToMany_Optional2].[OneToMany_Optional_Inverse3Id] = [t].[Id] -ORDER BY [t].[Id]"); + @"SELECT [l].[Id], [l].[OneToOne_Required_PK_Date], [l].[Level1_Optional_Id], [l].[Level1_Required_Id], [l].[Level2_Name], [l].[OneToMany_Optional_Inverse2Id], [l].[OneToMany_Required_Inverse2Id], [l].[OneToOne_Optional_PK_Inverse2Id], [l0].[Id], [l1].[Id], [l1].[Level2_Optional_Id], [l1].[Level2_Required_Id], [l1].[Level3_Name], [l1].[OneToMany_Optional_Inverse3Id], [l1].[OneToMany_Required_Inverse3Id], [l1].[OneToOne_Optional_PK_Inverse3Id] +FROM [Level1] AS [l0] +INNER JOIN [Level1] AS [l] ON [l0].[Id] = [l].[OneToMany_Optional_Inverse2Id] +LEFT JOIN [Level1] AS [l1] ON [l].[Id] = [l1].[OneToMany_Optional_Inverse3Id] +ORDER BY [l0].[Id], [l].[Id], [l1].[Id]"); } public override async Task Orderby_SelectMany_with_Include1(bool isAsync) @@ -2202,12 +2186,11 @@ public override async Task SelectMany_with_navigation_and_explicit_DefaultIfEmpt { await base.SelectMany_with_navigation_and_explicit_DefaultIfEmpty(isAsync); - // issue #15081 -// AssertSql( -// @"SELECT [l1].[Id], [l1].[Date], [l1].[Name], [l1].[OneToMany_Optional_Self_Inverse1Id], [l1].[OneToMany_Required_Self_Inverse1Id], [l1].[OneToOne_Optional_Self1Id] -//FROM [LevelOne] AS [l1] -//LEFT JOIN [LevelTwo] AS [l1.OneToMany_Optional1] ON [l1].[Id] = [l1.OneToMany_Optional1].[OneToMany_Optional_Inverse2Id] -//WHERE [l1.OneToMany_Optional1].[Id] IS NOT NULL"); + AssertSql( + @"SELECT [l1].[Id], [l1].[Date], [l1].[Name], [l1].[OneToMany_Optional_Self_Inverse1Id], [l1].[OneToMany_Required_Self_Inverse1Id], [l1].[OneToOne_Optional_Self1Id] +FROM [LevelOne] AS [l1] +LEFT JOIN [LevelTwo] AS [l1.OneToMany_Optional1] ON [l1].[Id] = [l1.OneToMany_Optional1].[OneToMany_Optional_Inverse2Id] +WHERE [l1.OneToMany_Optional1].[Id] IS NOT NULL"); } public override async Task SelectMany_with_navigation_and_Distinct(bool isAsync) @@ -2233,80 +2216,75 @@ public override async Task SelectMany_with_navigation_filter_and_explicit_Defaul { await base.SelectMany_with_navigation_filter_and_explicit_DefaultIfEmpty(isAsync); - // issue #15081 -// AssertSql( -// @"SELECT [l1].[Id], [l1].[Date], [l1].[Name], [l1].[OneToMany_Optional_Self_Inverse1Id], [l1].[OneToMany_Required_Self_Inverse1Id], [l1].[OneToOne_Optional_Self1Id] -//FROM [LevelOne] AS [l1] -//LEFT JOIN ( -// SELECT [l1.OneToMany_Optional1].* -// FROM [LevelTwo] AS [l1.OneToMany_Optional1] -// WHERE [l1.OneToMany_Optional1].[Id] > 5 -//) AS [t] ON [l1].[Id] = [t].[OneToMany_Optional_Inverse2Id] -//WHERE [t].[Id] IS NOT NULL"); + AssertSql( + @"SELECT [l1].[Id], [l1].[Date], [l1].[Name], [l1].[OneToMany_Optional_Self_Inverse1Id], [l1].[OneToMany_Required_Self_Inverse1Id], [l1].[OneToOne_Optional_Self1Id] +FROM [LevelOne] AS [l1] +LEFT JOIN ( + SELECT [l1.OneToMany_Optional1].* + FROM [LevelTwo] AS [l1.OneToMany_Optional1] + WHERE [l1.OneToMany_Optional1].[Id] > 5 +) AS [t] ON [l1].[Id] = [t].[OneToMany_Optional_Inverse2Id] +WHERE [t].[Id] IS NOT NULL"); } public override async Task SelectMany_with_nested_navigation_and_explicit_DefaultIfEmpty(bool isAsync) { await base.SelectMany_with_nested_navigation_and_explicit_DefaultIfEmpty(isAsync); - // issue #15081 -// AssertSql( -// @"SELECT [l1].[Id], [l1].[Date], [l1].[Name], [l1].[OneToMany_Optional_Self_Inverse1Id], [l1].[OneToMany_Required_Self_Inverse1Id], [l1].[OneToOne_Optional_Self1Id] -//FROM [LevelOne] AS [l1] -//LEFT JOIN [LevelTwo] AS [l1.OneToOne_Required_FK1] ON [l1].[Id] = [l1.OneToOne_Required_FK1].[Level1_Required_Id] -//LEFT JOIN [LevelThree] AS [l1.OneToOne_Required_FK1.OneToMany_Optional2] ON [l1.OneToOne_Required_FK1].[Id] = [l1.OneToOne_Required_FK1.OneToMany_Optional2].[OneToMany_Optional_Inverse3Id] -//WHERE [l1.OneToOne_Required_FK1.OneToMany_Optional2].[Id] IS NOT NULL"); + AssertSql( + @"SELECT [l1].[Id], [l1].[Date], [l1].[Name], [l1].[OneToMany_Optional_Self_Inverse1Id], [l1].[OneToMany_Required_Self_Inverse1Id], [l1].[OneToOne_Optional_Self1Id] +FROM [LevelOne] AS [l1] +LEFT JOIN [LevelTwo] AS [l1.OneToOne_Required_FK1] ON [l1].[Id] = [l1.OneToOne_Required_FK1].[Level1_Required_Id] +LEFT JOIN [LevelThree] AS [l1.OneToOne_Required_FK1.OneToMany_Optional2] ON [l1.OneToOne_Required_FK1].[Id] = [l1.OneToOne_Required_FK1.OneToMany_Optional2].[OneToMany_Optional_Inverse3Id] +WHERE [l1.OneToOne_Required_FK1.OneToMany_Optional2].[Id] IS NOT NULL"); } public override async Task SelectMany_with_nested_navigation_filter_and_explicit_DefaultIfEmpty(bool isAsync) { await base.SelectMany_with_nested_navigation_filter_and_explicit_DefaultIfEmpty(isAsync); - // issue #15081 -// AssertSql( -// @"SELECT [l1].[Id], [l1].[Date], [l1].[Name], [l1].[OneToMany_Optional_Self_Inverse1Id], [l1].[OneToMany_Required_Self_Inverse1Id], [l1].[OneToOne_Optional_Self1Id] -//FROM [LevelOne] AS [l1] -//LEFT JOIN [LevelTwo] AS [l1.OneToOne_Optional_FK1] ON [l1].[Id] = [l1.OneToOne_Optional_FK1].[Level1_Optional_Id] -//LEFT JOIN ( -// SELECT [l1.OneToOne_Optional_FK1.OneToMany_Optional2].* -// FROM [LevelThree] AS [l1.OneToOne_Optional_FK1.OneToMany_Optional2] -// WHERE [l1.OneToOne_Optional_FK1.OneToMany_Optional2].[Id] > 5 -//) AS [t] ON [l1.OneToOne_Optional_FK1].[Id] = [t].[OneToMany_Optional_Inverse3Id] -//WHERE [t].[Id] IS NOT NULL"); + AssertSql( + @"SELECT [l1].[Id], [l1].[Date], [l1].[Name], [l1].[OneToMany_Optional_Self_Inverse1Id], [l1].[OneToMany_Required_Self_Inverse1Id], [l1].[OneToOne_Optional_Self1Id] +FROM [LevelOne] AS [l1] +LEFT JOIN [LevelTwo] AS [l1.OneToOne_Optional_FK1] ON [l1].[Id] = [l1.OneToOne_Optional_FK1].[Level1_Optional_Id] +LEFT JOIN ( + SELECT [l1.OneToOne_Optional_FK1.OneToMany_Optional2].* + FROM [LevelThree] AS [l1.OneToOne_Optional_FK1.OneToMany_Optional2] + WHERE [l1.OneToOne_Optional_FK1.OneToMany_Optional2].[Id] > 5 +) AS [t] ON [l1.OneToOne_Optional_FK1].[Id] = [t].[OneToMany_Optional_Inverse3Id] +WHERE [t].[Id] IS NOT NULL"); } public override async Task SelectMany_with_nested_required_navigation_filter_and_explicit_DefaultIfEmpty(bool isAsync) { await base.SelectMany_with_nested_required_navigation_filter_and_explicit_DefaultIfEmpty(isAsync); - // issue #15081 -// AssertSql( -// @"SELECT [l1].[Id], [l1].[Date], [l1].[Name], [l1].[OneToMany_Optional_Self_Inverse1Id], [l1].[OneToMany_Required_Self_Inverse1Id], [l1].[OneToOne_Optional_Self1Id] -//FROM [LevelOne] AS [l1] -//LEFT JOIN [LevelTwo] AS [l1.OneToOne_Required_FK1] ON [l1].[Id] = [l1.OneToOne_Required_FK1].[Level1_Required_Id] -//LEFT JOIN ( -// SELECT [l1.OneToOne_Required_FK1.OneToMany_Required2].* -// FROM [LevelThree] AS [l1.OneToOne_Required_FK1.OneToMany_Required2] -// WHERE [l1.OneToOne_Required_FK1.OneToMany_Required2].[Id] > 5 -//) AS [t] ON [l1.OneToOne_Required_FK1].[Id] = [t].[OneToMany_Required_Inverse3Id] -//WHERE [t].[Id] IS NOT NULL"); + AssertSql( + @"SELECT [l1].[Id], [l1].[Date], [l1].[Name], [l1].[OneToMany_Optional_Self_Inverse1Id], [l1].[OneToMany_Required_Self_Inverse1Id], [l1].[OneToOne_Optional_Self1Id] +FROM [LevelOne] AS [l1] +LEFT JOIN [LevelTwo] AS [l1.OneToOne_Required_FK1] ON [l1].[Id] = [l1.OneToOne_Required_FK1].[Level1_Required_Id] +LEFT JOIN ( + SELECT [l1.OneToOne_Required_FK1.OneToMany_Required2].* + FROM [LevelThree] AS [l1.OneToOne_Required_FK1.OneToMany_Required2] + WHERE [l1.OneToOne_Required_FK1.OneToMany_Required2].[Id] > 5 +) AS [t] ON [l1.OneToOne_Required_FK1].[Id] = [t].[OneToMany_Required_Inverse3Id] +WHERE [t].[Id] IS NOT NULL"); } public override void SelectMany_with_nested_navigations_and_additional_joins_outside_of_SelectMany() { base.SelectMany_with_nested_navigations_and_additional_joins_outside_of_SelectMany(); - // issue #15081 -// AssertSql( -// @"SELECT [l1].[Id], [l1].[Date], [l1].[Name], [l1].[OneToMany_Optional_Self_Inverse1Id], [l1].[OneToMany_Required_Self_Inverse1Id], [l1].[OneToOne_Optional_Self1Id], [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 [LevelOne] AS [l1] -//INNER JOIN ( -// SELECT [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Date], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Level1_Optional_Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Level1_Required_Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Name], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Optional_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Optional_Self_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Self_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToOne_Optional_PK_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToOne_Optional_Self2Id] -// FROM [LevelFour] AS [l4] -// INNER JOIN [LevelThree] AS [l4.OneToOne_Required_FK_Inverse4] ON [l4].[Level3_Required_Id] = [l4.OneToOne_Required_FK_Inverse4].[Id] -// INNER JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3] ON [l4.OneToOne_Required_FK_Inverse4].[Level2_Optional_Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3].[Id] -// INNER JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2] ON [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3].[Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Self_Inverse2Id] -//) AS [t] ON [l1].[Id] = [t].[Level1_Optional_Id]"); + AssertSql( + @"SELECT [l1].[Id], [l1].[Date], [l1].[Name], [l1].[OneToMany_Optional_Self_Inverse1Id], [l1].[OneToMany_Required_Self_Inverse1Id], [l1].[OneToOne_Optional_Self1Id], [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 [LevelOne] AS [l1] +INNER JOIN ( + SELECT [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Date], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Level1_Optional_Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Level1_Required_Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Name], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Optional_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Optional_Self_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Self_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToOne_Optional_PK_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToOne_Optional_Self2Id] + FROM [LevelFour] AS [l4] + INNER JOIN [LevelThree] AS [l4.OneToOne_Required_FK_Inverse4] ON [l4].[Level3_Required_Id] = [l4.OneToOne_Required_FK_Inverse4].[Id] + INNER JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3] ON [l4.OneToOne_Required_FK_Inverse4].[Level2_Optional_Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3].[Id] + INNER JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2] ON [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3].[Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Self_Inverse2Id] +) AS [t] ON [l1].[Id] = [t].[Level1_Optional_Id]"); } public override async Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany( @@ -2314,17 +2292,16 @@ public override async Task SelectMany_with_nested_navigations_explicit_DefaultIf { await base.SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany(isAsync); - // issue #15081 -// AssertSql( -// @"SELECT [l1].[Id], [l1].[Date], [l1].[Name], [l1].[OneToMany_Optional_Self_Inverse1Id], [l1].[OneToMany_Required_Self_Inverse1Id], [l1].[OneToOne_Optional_Self1Id], [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 [LevelOne] AS [l1] -//INNER JOIN ( -// SELECT [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Date], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Level1_Optional_Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Level1_Required_Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Name], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Optional_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Optional_Self_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Self_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToOne_Optional_PK_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToOne_Optional_Self2Id] -// FROM [LevelFour] AS [l4] -// LEFT JOIN [LevelThree] AS [l4.OneToOne_Required_FK_Inverse4] ON [l4].[Level3_Required_Id] = [l4.OneToOne_Required_FK_Inverse4].[Id] -// LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3] ON [l4.OneToOne_Required_FK_Inverse4].[Level2_Optional_Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3].[Id] -// LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2] ON [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3].[Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Self_Inverse2Id] -//) AS [t] ON [l1].[Id] = [t].[Level1_Optional_Id]"); + AssertSql( + @"SELECT [l1].[Id], [l1].[Date], [l1].[Name], [l1].[OneToMany_Optional_Self_Inverse1Id], [l1].[OneToMany_Required_Self_Inverse1Id], [l1].[OneToOne_Optional_Self1Id], [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 [LevelOne] AS [l1] +INNER JOIN ( + SELECT [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Date], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Level1_Optional_Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Level1_Required_Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Name], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Optional_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Optional_Self_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Self_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToOne_Optional_PK_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToOne_Optional_Self2Id] + FROM [LevelFour] AS [l4] + LEFT JOIN [LevelThree] AS [l4.OneToOne_Required_FK_Inverse4] ON [l4].[Level3_Required_Id] = [l4.OneToOne_Required_FK_Inverse4].[Id] + LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3] ON [l4.OneToOne_Required_FK_Inverse4].[Level2_Optional_Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3].[Id] + LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2] ON [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3].[Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Self_Inverse2Id] +) AS [t] ON [l1].[Id] = [t].[Level1_Optional_Id]"); } public override async Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany2( @@ -2332,14 +2309,13 @@ public override async Task SelectMany_with_nested_navigations_explicit_DefaultIf { await base.SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany2(isAsync); - // issue #15081 -// AssertSql( -// @"SELECT [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Date], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Level1_Optional_Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Level1_Required_Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Name], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Optional_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Optional_Self_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Self_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToOne_Optional_PK_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToOne_Optional_Self2Id], [l1].[Id], [l1].[Date], [l1].[Name], [l1].[OneToMany_Optional_Self_Inverse1Id], [l1].[OneToMany_Required_Self_Inverse1Id], [l1].[OneToOne_Optional_Self1Id] -//FROM [LevelFour] AS [l4] -//LEFT JOIN [LevelThree] AS [l4.OneToOne_Required_FK_Inverse4] ON [l4].[Level3_Required_Id] = [l4.OneToOne_Required_FK_Inverse4].[Id] -//LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3] ON [l4.OneToOne_Required_FK_Inverse4].[Level2_Optional_Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3].[Id] -//LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2] ON [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3].[Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Self_Inverse2Id] -//INNER JOIN [LevelOne] AS [l1] ON [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Level1_Optional_Id] = [l1].[Id]"); + AssertSql( + @"SELECT [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Date], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Level1_Optional_Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Level1_Required_Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Name], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Optional_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Optional_Self_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Self_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToOne_Optional_PK_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToOne_Optional_Self2Id], [l1].[Id], [l1].[Date], [l1].[Name], [l1].[OneToMany_Optional_Self_Inverse1Id], [l1].[OneToMany_Required_Self_Inverse1Id], [l1].[OneToOne_Optional_Self1Id] +FROM [LevelFour] AS [l4] +LEFT JOIN [LevelThree] AS [l4.OneToOne_Required_FK_Inverse4] ON [l4].[Level3_Required_Id] = [l4.OneToOne_Required_FK_Inverse4].[Id] +LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3] ON [l4.OneToOne_Required_FK_Inverse4].[Level2_Optional_Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3].[Id] +LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2] ON [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3].[Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Self_Inverse2Id] +INNER JOIN [LevelOne] AS [l1] ON [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Level1_Optional_Id] = [l1].[Id]"); } public override async Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany3( @@ -2347,14 +2323,13 @@ public override async Task SelectMany_with_nested_navigations_explicit_DefaultIf { await base.SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany3(isAsync); - // issue #15081 -// AssertSql( -// @"SELECT [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Level3_Optional_Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Level3_Required_Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Name], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Optional_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Optional_Self_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Required_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Required_Self_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToOne_Optional_PK_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToOne_Optional_Self4Id], [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 [LevelOne] AS [l1] -//LEFT JOIN [LevelTwo] AS [l1.OneToOne_Required_FK1] ON [l1].[Id] = [l1.OneToOne_Required_FK1].[Level1_Required_Id] -//LEFT JOIN [LevelThree] AS [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2] ON [l1.OneToOne_Required_FK1].[Id] = [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2].[Level2_Optional_Id] -//LEFT JOIN [LevelFour] AS [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3] ON [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2].[Id] = [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Required_Inverse4Id] -//INNER JOIN [LevelTwo] AS [l2] ON [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Id] = [l2].[Id]"); + AssertSql( + @"SELECT [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Level3_Optional_Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Level3_Required_Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Name], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Optional_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Optional_Self_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Required_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Required_Self_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToOne_Optional_PK_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToOne_Optional_Self4Id], [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 [LevelOne] AS [l1] +LEFT JOIN [LevelTwo] AS [l1.OneToOne_Required_FK1] ON [l1].[Id] = [l1.OneToOne_Required_FK1].[Level1_Required_Id] +LEFT JOIN [LevelThree] AS [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2] ON [l1.OneToOne_Required_FK1].[Id] = [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2].[Level2_Optional_Id] +LEFT JOIN [LevelFour] AS [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3] ON [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2].[Id] = [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Required_Inverse4Id] +INNER JOIN [LevelTwo] AS [l2] ON [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Id] = [l2].[Id]"); } public override async Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany4( @@ -2362,63 +2337,59 @@ public override async Task SelectMany_with_nested_navigations_explicit_DefaultIf { await base.SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany4(isAsync); - // issue #15081 -// AssertSql( -// @"SELECT [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Level3_Optional_Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Level3_Required_Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Name], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Optional_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Optional_Self_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Required_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Required_Self_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToOne_Optional_PK_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToOne_Optional_Self4Id], [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 [LevelOne] AS [l1] -//LEFT JOIN [LevelTwo] AS [l1.OneToOne_Required_FK1] ON [l1].[Id] = [l1.OneToOne_Required_FK1].[Level1_Required_Id] -//LEFT JOIN [LevelThree] AS [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2] ON [l1.OneToOne_Required_FK1].[Id] = [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2].[Level2_Optional_Id] -//LEFT JOIN [LevelFour] AS [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3] ON [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2].[Id] = [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Required_Inverse4Id] -//LEFT JOIN [LevelTwo] AS [l2] ON [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Id] = [l2].[Id]"); + AssertSql( + @"SELECT [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Level3_Optional_Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Level3_Required_Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Name], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Optional_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Optional_Self_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Required_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Required_Self_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToOne_Optional_PK_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToOne_Optional_Self4Id], [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 [LevelOne] AS [l1] +LEFT JOIN [LevelTwo] AS [l1.OneToOne_Required_FK1] ON [l1].[Id] = [l1.OneToOne_Required_FK1].[Level1_Required_Id] +LEFT JOIN [LevelThree] AS [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2] ON [l1.OneToOne_Required_FK1].[Id] = [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2].[Level2_Optional_Id] +LEFT JOIN [LevelFour] AS [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3] ON [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2].[Id] = [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Required_Inverse4Id] +LEFT JOIN [LevelTwo] AS [l2] ON [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Id] = [l2].[Id]"); } public override async Task Multiple_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_joined_together(bool isAsync) { await base.Multiple_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_joined_together(isAsync); - // issue #15081 -// AssertSql( -// @"SELECT [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Level3_Optional_Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Level3_Required_Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Name], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Optional_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Optional_Self_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Required_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Required_Self_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToOne_Optional_PK_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToOne_Optional_Self4Id], [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 [LevelOne] AS [l1] -//LEFT JOIN [LevelTwo] AS [l1.OneToOne_Required_FK1] ON [l1].[Id] = [l1.OneToOne_Required_FK1].[Level1_Required_Id] -//LEFT JOIN [LevelThree] AS [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2] ON [l1.OneToOne_Required_FK1].[Id] = [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2].[Level2_Optional_Id] -//LEFT JOIN [LevelFour] AS [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3] ON [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2].[Id] = [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Required_Inverse4Id] -//INNER JOIN ( -// SELECT [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Date], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Level1_Optional_Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Level1_Required_Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Name], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Optional_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Optional_Self_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Self_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToOne_Optional_PK_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToOne_Optional_Self2Id] -// FROM [LevelFour] AS [l4] -// LEFT JOIN [LevelThree] AS [l4.OneToOne_Required_FK_Inverse4] ON [l4].[Level3_Required_Id] = [l4.OneToOne_Required_FK_Inverse4].[Id] -// LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3] ON [l4.OneToOne_Required_FK_Inverse4].[Level2_Optional_Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3].[Id] -// LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2] ON [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3].[Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Self_Inverse2Id] -//) AS [t] ON [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Id] = [t].[Id]"); + AssertSql( + @"SELECT [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Level3_Optional_Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Level3_Required_Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Name], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Optional_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Optional_Self_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Required_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Required_Self_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToOne_Optional_PK_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToOne_Optional_Self4Id], [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 [LevelOne] AS [l1] +LEFT JOIN [LevelTwo] AS [l1.OneToOne_Required_FK1] ON [l1].[Id] = [l1.OneToOne_Required_FK1].[Level1_Required_Id] +LEFT JOIN [LevelThree] AS [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2] ON [l1.OneToOne_Required_FK1].[Id] = [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2].[Level2_Optional_Id] +LEFT JOIN [LevelFour] AS [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3] ON [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2].[Id] = [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Required_Inverse4Id] +INNER JOIN ( + SELECT [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Date], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Level1_Optional_Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Level1_Required_Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[Name], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Optional_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Optional_Self_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Self_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToOne_Optional_PK_Inverse2Id], [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToOne_Optional_Self2Id] + FROM [LevelFour] AS [l4] + LEFT JOIN [LevelThree] AS [l4.OneToOne_Required_FK_Inverse4] ON [l4].[Level3_Required_Id] = [l4.OneToOne_Required_FK_Inverse4].[Id] + LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3] ON [l4.OneToOne_Required_FK_Inverse4].[Level2_Optional_Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3].[Id] + LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2] ON [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3].[Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Self_Inverse2Id] +) AS [t] ON [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Id] = [t].[Id]"); } public override async Task SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_followed_by_Select_required_navigation_using_same_navs(bool isAsync) { await base.SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_followed_by_Select_required_navigation_using_same_navs(isAsync); - // issue #15081 -// AssertSql( -// @"SELECT [OneToOne_Required_FK_Inverse3.OneToMany_Required2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[Id], [OneToOne_Required_FK_Inverse3.OneToMany_Required2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[Date], [OneToOne_Required_FK_Inverse3.OneToMany_Required2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[Name], [OneToOne_Required_FK_Inverse3.OneToMany_Required2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[OneToMany_Optional_Self_Inverse1Id], [OneToOne_Required_FK_Inverse3.OneToMany_Required2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[OneToMany_Required_Self_Inverse1Id], [OneToOne_Required_FK_Inverse3.OneToMany_Required2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[OneToOne_Optional_Self1Id] -//FROM [LevelFour] AS [l4] -//LEFT JOIN [LevelThree] AS [l4.OneToOne_Required_FK_Inverse4] ON [l4].[Level3_Required_Id] = [l4.OneToOne_Required_FK_Inverse4].[Id] -//LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3] ON [l4.OneToOne_Required_FK_Inverse4].[Level2_Required_Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3].[Id] -//LEFT JOIN [LevelThree] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3.OneToMany_Required2] ON [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3].[Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3.OneToMany_Required2].[OneToMany_Required_Inverse3Id] -//LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3.OneToMany_Required2.OneToOne_Required_FK_Inverse3] ON [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3.OneToMany_Required2].[Level2_Required_Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3.OneToMany_Required2.OneToOne_Required_FK_Inverse3].[Id] -//LEFT JOIN [LevelOne] AS [OneToOne_Required_FK_Inverse3.OneToMany_Required2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2] ON [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3.OneToMany_Required2.OneToOne_Required_FK_Inverse3].[Id] = [OneToOne_Required_FK_Inverse3.OneToMany_Required2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[Id]"); + AssertSql( + @"SELECT [OneToOne_Required_FK_Inverse3.OneToMany_Required2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[Id], [OneToOne_Required_FK_Inverse3.OneToMany_Required2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[Date], [OneToOne_Required_FK_Inverse3.OneToMany_Required2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[Name], [OneToOne_Required_FK_Inverse3.OneToMany_Required2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[OneToMany_Optional_Self_Inverse1Id], [OneToOne_Required_FK_Inverse3.OneToMany_Required2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[OneToMany_Required_Self_Inverse1Id], [OneToOne_Required_FK_Inverse3.OneToMany_Required2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[OneToOne_Optional_Self1Id] +FROM [LevelFour] AS [l4] +LEFT JOIN [LevelThree] AS [l4.OneToOne_Required_FK_Inverse4] ON [l4].[Level3_Required_Id] = [l4.OneToOne_Required_FK_Inverse4].[Id] +LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3] ON [l4.OneToOne_Required_FK_Inverse4].[Level2_Required_Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3].[Id] +LEFT JOIN [LevelThree] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3.OneToMany_Required2] ON [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3].[Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3.OneToMany_Required2].[OneToMany_Required_Inverse3Id] +LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3.OneToMany_Required2.OneToOne_Required_FK_Inverse3] ON [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3.OneToMany_Required2].[Level2_Required_Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3.OneToMany_Required2.OneToOne_Required_FK_Inverse3].[Id] +LEFT JOIN [LevelOne] AS [OneToOne_Required_FK_Inverse3.OneToMany_Required2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2] ON [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3.OneToMany_Required2.OneToOne_Required_FK_Inverse3].[Id] = [OneToOne_Required_FK_Inverse3.OneToMany_Required2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[Id]"); } public override async Task SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_followed_by_Select_required_navigation_using_different_navs(bool isAsync) { await base.SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_followed_by_Select_required_navigation_using_different_navs(isAsync); - // issue #15081 -// AssertSql( -// @"SELECT [l1.OneToOne_Optional_FK1.OneToMany_Optional2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[Id], [l1.OneToOne_Optional_FK1.OneToMany_Optional2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[Date], [l1.OneToOne_Optional_FK1.OneToMany_Optional2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[Name], [l1.OneToOne_Optional_FK1.OneToMany_Optional2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[OneToMany_Optional_Self_Inverse1Id], [l1.OneToOne_Optional_FK1.OneToMany_Optional2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[OneToMany_Required_Self_Inverse1Id], [l1.OneToOne_Optional_FK1.OneToMany_Optional2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[OneToOne_Optional_Self1Id] -//FROM [LevelOne] AS [l1] -//LEFT JOIN [LevelTwo] AS [l1.OneToOne_Optional_FK1] ON [l1].[Id] = [l1.OneToOne_Optional_FK1].[Level1_Optional_Id] -//LEFT JOIN [LevelThree] AS [l1.OneToOne_Optional_FK1.OneToMany_Optional2] ON [l1.OneToOne_Optional_FK1].[Id] = [l1.OneToOne_Optional_FK1.OneToMany_Optional2].[OneToMany_Optional_Inverse3Id] -//LEFT JOIN [LevelTwo] AS [l1.OneToOne_Optional_FK1.OneToMany_Optional2.OneToOne_Required_FK_Inverse3] ON [l1.OneToOne_Optional_FK1.OneToMany_Optional2].[Level2_Required_Id] = [l1.OneToOne_Optional_FK1.OneToMany_Optional2.OneToOne_Required_FK_Inverse3].[Id] -//LEFT JOIN [LevelOne] AS [l1.OneToOne_Optional_FK1.OneToMany_Optional2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2] ON [l1.OneToOne_Optional_FK1.OneToMany_Optional2.OneToOne_Required_FK_Inverse3].[Id] = [l1.OneToOne_Optional_FK1.OneToMany_Optional2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[Id]"); + AssertSql( + @"SELECT [l1.OneToOne_Optional_FK1.OneToMany_Optional2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[Id], [l1.OneToOne_Optional_FK1.OneToMany_Optional2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[Date], [l1.OneToOne_Optional_FK1.OneToMany_Optional2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[Name], [l1.OneToOne_Optional_FK1.OneToMany_Optional2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[OneToMany_Optional_Self_Inverse1Id], [l1.OneToOne_Optional_FK1.OneToMany_Optional2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[OneToMany_Required_Self_Inverse1Id], [l1.OneToOne_Optional_FK1.OneToMany_Optional2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[OneToOne_Optional_Self1Id] +FROM [LevelOne] AS [l1] +LEFT JOIN [LevelTwo] AS [l1.OneToOne_Optional_FK1] ON [l1].[Id] = [l1.OneToOne_Optional_FK1].[Level1_Optional_Id] +LEFT JOIN [LevelThree] AS [l1.OneToOne_Optional_FK1.OneToMany_Optional2] ON [l1.OneToOne_Optional_FK1].[Id] = [l1.OneToOne_Optional_FK1.OneToMany_Optional2].[OneToMany_Optional_Inverse3Id] +LEFT JOIN [LevelTwo] AS [l1.OneToOne_Optional_FK1.OneToMany_Optional2.OneToOne_Required_FK_Inverse3] ON [l1.OneToOne_Optional_FK1.OneToMany_Optional2].[Level2_Required_Id] = [l1.OneToOne_Optional_FK1.OneToMany_Optional2.OneToOne_Required_FK_Inverse3].[Id] +LEFT JOIN [LevelOne] AS [l1.OneToOne_Optional_FK1.OneToMany_Optional2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2] ON [l1.OneToOne_Optional_FK1.OneToMany_Optional2.OneToOne_Required_FK_Inverse3].[Id] = [l1.OneToOne_Optional_FK1.OneToMany_Optional2.OneToOne_Required_FK_Inverse3.OneToOne_Required_PK_Inverse2].[Id]"); } public override async Task @@ -2427,81 +2398,79 @@ public override async Task await base.Complex_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_with_other_query_operators_composed_on_top( isAsync); - // issue #15081 -// AssertSql( -// @"SELECT [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Level3_Optional_Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Level3_Required_Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Name], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Optional_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Optional_Self_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Required_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Required_Self_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToOne_Optional_PK_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToOne_Optional_Self4Id], [l3.OneToOne_Optional_FK_Inverse3.OneToOne_Required_FK2].[Name] AS [Property], [t].[Id] -//FROM [LevelOne] AS [l1] -//LEFT JOIN [LevelTwo] AS [l1.OneToOne_Required_FK1] ON [l1].[Id] = [l1.OneToOne_Required_FK1].[Level1_Required_Id] -//LEFT JOIN [LevelThree] AS [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2] ON [l1.OneToOne_Required_FK1].[Id] = [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2].[Level2_Optional_Id] -//LEFT JOIN [LevelFour] AS [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3] ON [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2].[Id] = [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Required_Inverse4Id] -//LEFT JOIN [LevelThree] AS [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3.OneToMany_Optional_Inverse4] ON [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Optional_Inverse4Id] = [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3.OneToMany_Optional_Inverse4].[Id] -//INNER JOIN ( -// SELECT [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].* -// FROM [LevelFour] AS [l4] -// LEFT JOIN [LevelThree] AS [l4.OneToOne_Required_FK_Inverse4] ON [l4].[Level3_Required_Id] = [l4.OneToOne_Required_FK_Inverse4].[Id] -// LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3] ON [l4.OneToOne_Required_FK_Inverse4].[Level2_Optional_Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3].[Id] -// LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2] ON [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3].[Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Self_Inverse2Id] -//) AS [t] ON [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Id] = [t].[Id] -//LEFT JOIN [LevelThree] AS [l2.OneToOne_Optional_FK2] ON [t].[Id] = [l2.OneToOne_Optional_FK2].[Level2_Optional_Id] -//LEFT JOIN ( -// SELECT [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3.OneToMany_Required2].* -// FROM [LevelFour] AS [l40] -// LEFT JOIN [LevelThree] AS [l4.OneToOne_Required_FK_Inverse40] ON [l40].[Level3_Required_Id] = [l4.OneToOne_Required_FK_Inverse40].[Id] -// LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3] ON [l4.OneToOne_Required_FK_Inverse40].[Level2_Required_Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3].[Id] -// LEFT JOIN [LevelThree] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3.OneToMany_Required2] ON [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3].[Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3.OneToMany_Required2].[OneToMany_Required_Inverse3Id] -//) AS [t0] ON [t].[Id] = [t0].[Id] -//LEFT JOIN [LevelTwo] AS [l3.OneToOne_Optional_FK_Inverse3] ON [t0].[Level2_Optional_Id] = [l3.OneToOne_Optional_FK_Inverse3].[Id] -//LEFT JOIN [LevelThree] AS [l3.OneToOne_Optional_FK_Inverse3.OneToOne_Required_FK2] ON [l3.OneToOne_Optional_FK_Inverse3].[Id] = [l3.OneToOne_Optional_FK_Inverse3.OneToOne_Required_FK2].[Level2_Required_Id] -//WHERE ([l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3.OneToMany_Optional_Inverse4].[Name] <> N'Foo') OR [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3.OneToMany_Optional_Inverse4].[Name] IS NULL -//ORDER BY [l2.OneToOne_Optional_FK2].[Id], [t].[Id]", -// // -// @"SELECT [l2.OneToMany_Optional_Self2].[Id], [l2.OneToMany_Optional_Self2].[Date], [l2.OneToMany_Optional_Self2].[Level1_Optional_Id], [l2.OneToMany_Optional_Self2].[Level1_Required_Id], [l2.OneToMany_Optional_Self2].[Name], [l2.OneToMany_Optional_Self2].[OneToMany_Optional_Inverse2Id], [l2.OneToMany_Optional_Self2].[OneToMany_Optional_Self_Inverse2Id], [l2.OneToMany_Optional_Self2].[OneToMany_Required_Inverse2Id], [l2.OneToMany_Optional_Self2].[OneToMany_Required_Self_Inverse2Id], [l2.OneToMany_Optional_Self2].[OneToOne_Optional_PK_Inverse2Id], [l2.OneToMany_Optional_Self2].[OneToOne_Optional_Self2Id], [t3].[Id], [t3].[Id0] -//FROM [LevelTwo] AS [l2.OneToMany_Optional_Self2] -//INNER JOIN ( -// SELECT [l2.OneToOne_Optional_FK20].[Id], [t1].[Id] AS [Id0] -// FROM [LevelOne] AS [l10] -// LEFT JOIN [LevelTwo] AS [l1.OneToOne_Required_FK10] ON [l10].[Id] = [l1.OneToOne_Required_FK10].[Level1_Required_Id] -// LEFT JOIN [LevelThree] AS [l1.OneToOne_Required_FK1.OneToOne_Optional_FK20] ON [l1.OneToOne_Required_FK10].[Id] = [l1.OneToOne_Required_FK1.OneToOne_Optional_FK20].[Level2_Optional_Id] -// LEFT JOIN [LevelFour] AS [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required30] ON [l1.OneToOne_Required_FK1.OneToOne_Optional_FK20].[Id] = [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required30].[OneToMany_Required_Inverse4Id] -// LEFT JOIN [LevelThree] AS [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3.OneToMany_Optional_Inverse40] ON [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required30].[OneToMany_Optional_Inverse4Id] = [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3.OneToMany_Optional_Inverse40].[Id] -// INNER JOIN ( -// SELECT [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self20].* -// FROM [LevelFour] AS [l41] -// LEFT JOIN [LevelThree] AS [l4.OneToOne_Required_FK_Inverse41] ON [l41].[Level3_Required_Id] = [l4.OneToOne_Required_FK_Inverse41].[Id] -// LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse30] ON [l4.OneToOne_Required_FK_Inverse41].[Level2_Optional_Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse30].[Id] -// LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self20] ON [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse30].[Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self20].[OneToMany_Required_Self_Inverse2Id] -// ) AS [t1] ON [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required30].[Id] = [t1].[Id] -// LEFT JOIN [LevelThree] AS [l2.OneToOne_Optional_FK20] ON [t1].[Id] = [l2.OneToOne_Optional_FK20].[Level2_Optional_Id] -// LEFT JOIN ( -// SELECT [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3.OneToMany_Required20].* -// FROM [LevelFour] AS [l42] -// LEFT JOIN [LevelThree] AS [l4.OneToOne_Required_FK_Inverse42] ON [l42].[Level3_Required_Id] = [l4.OneToOne_Required_FK_Inverse42].[Id] -// LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse30] ON [l4.OneToOne_Required_FK_Inverse42].[Level2_Required_Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse30].[Id] -// LEFT JOIN [LevelThree] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3.OneToMany_Required20] ON [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse30].[Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3.OneToMany_Required20].[OneToMany_Required_Inverse3Id] -// ) AS [t2] ON [t1].[Id] = [t2].[Id] -// LEFT JOIN [LevelTwo] AS [l3.OneToOne_Optional_FK_Inverse30] ON [t2].[Level2_Optional_Id] = [l3.OneToOne_Optional_FK_Inverse30].[Id] -// LEFT JOIN [LevelThree] AS [l3.OneToOne_Optional_FK_Inverse3.OneToOne_Required_FK20] ON [l3.OneToOne_Optional_FK_Inverse30].[Id] = [l3.OneToOne_Optional_FK_Inverse3.OneToOne_Required_FK20].[Level2_Required_Id] -// WHERE ([l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3.OneToMany_Optional_Inverse40].[Name] <> N'Foo') OR [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3.OneToMany_Optional_Inverse40].[Name] IS NULL -//) AS [t3] ON [l2.OneToMany_Optional_Self2].[OneToMany_Optional_Self_Inverse2Id] = [t3].[Id0] -//WHERE [l2.OneToMany_Optional_Self2].[Id] <> 42 -//ORDER BY [t3].[Id], [t3].[Id0]"); + AssertSql( + @"SELECT [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Level3_Optional_Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Level3_Required_Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Name], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Optional_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Optional_Self_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Required_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Required_Self_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToOne_Optional_PK_Inverse4Id], [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToOne_Optional_Self4Id], [l3.OneToOne_Optional_FK_Inverse3.OneToOne_Required_FK2].[Name] AS [Property], [t].[Id] +FROM [LevelOne] AS [l1] +LEFT JOIN [LevelTwo] AS [l1.OneToOne_Required_FK1] ON [l1].[Id] = [l1.OneToOne_Required_FK1].[Level1_Required_Id] +LEFT JOIN [LevelThree] AS [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2] ON [l1.OneToOne_Required_FK1].[Id] = [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2].[Level2_Optional_Id] +LEFT JOIN [LevelFour] AS [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3] ON [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2].[Id] = [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Required_Inverse4Id] +LEFT JOIN [LevelThree] AS [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3.OneToMany_Optional_Inverse4] ON [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[OneToMany_Optional_Inverse4Id] = [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3.OneToMany_Optional_Inverse4].[Id] +INNER JOIN ( + SELECT [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].* + FROM [LevelFour] AS [l4] + LEFT JOIN [LevelThree] AS [l4.OneToOne_Required_FK_Inverse4] ON [l4].[Level3_Required_Id] = [l4.OneToOne_Required_FK_Inverse4].[Id] + LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3] ON [l4.OneToOne_Required_FK_Inverse4].[Level2_Optional_Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3].[Id] + LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2] ON [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3].[Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self2].[OneToMany_Required_Self_Inverse2Id] +) AS [t] ON [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3].[Id] = [t].[Id] +LEFT JOIN [LevelThree] AS [l2.OneToOne_Optional_FK2] ON [t].[Id] = [l2.OneToOne_Optional_FK2].[Level2_Optional_Id] +LEFT JOIN ( + SELECT [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3.OneToMany_Required2].* + FROM [LevelFour] AS [l40] + LEFT JOIN [LevelThree] AS [l4.OneToOne_Required_FK_Inverse40] ON [l40].[Level3_Required_Id] = [l4.OneToOne_Required_FK_Inverse40].[Id] + LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3] ON [l4.OneToOne_Required_FK_Inverse40].[Level2_Required_Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3].[Id] + LEFT JOIN [LevelThree] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3.OneToMany_Required2] ON [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3].[Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3.OneToMany_Required2].[OneToMany_Required_Inverse3Id] +) AS [t0] ON [t].[Id] = [t0].[Id] +LEFT JOIN [LevelTwo] AS [l3.OneToOne_Optional_FK_Inverse3] ON [t0].[Level2_Optional_Id] = [l3.OneToOne_Optional_FK_Inverse3].[Id] +LEFT JOIN [LevelThree] AS [l3.OneToOne_Optional_FK_Inverse3.OneToOne_Required_FK2] ON [l3.OneToOne_Optional_FK_Inverse3].[Id] = [l3.OneToOne_Optional_FK_Inverse3.OneToOne_Required_FK2].[Level2_Required_Id] +WHERE ([l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3.OneToMany_Optional_Inverse4].[Name] <> N'Foo') OR [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3.OneToMany_Optional_Inverse4].[Name] IS NULL +ORDER BY [l2.OneToOne_Optional_FK2].[Id], [t].[Id]", + // + @"SELECT [l2.OneToMany_Optional_Self2].[Id], [l2.OneToMany_Optional_Self2].[Date], [l2.OneToMany_Optional_Self2].[Level1_Optional_Id], [l2.OneToMany_Optional_Self2].[Level1_Required_Id], [l2.OneToMany_Optional_Self2].[Name], [l2.OneToMany_Optional_Self2].[OneToMany_Optional_Inverse2Id], [l2.OneToMany_Optional_Self2].[OneToMany_Optional_Self_Inverse2Id], [l2.OneToMany_Optional_Self2].[OneToMany_Required_Inverse2Id], [l2.OneToMany_Optional_Self2].[OneToMany_Required_Self_Inverse2Id], [l2.OneToMany_Optional_Self2].[OneToOne_Optional_PK_Inverse2Id], [l2.OneToMany_Optional_Self2].[OneToOne_Optional_Self2Id], [t3].[Id], [t3].[Id0] +FROM [LevelTwo] AS [l2.OneToMany_Optional_Self2] +INNER JOIN ( + SELECT [l2.OneToOne_Optional_FK20].[Id], [t1].[Id] AS [Id0] + FROM [LevelOne] AS [l10] + LEFT JOIN [LevelTwo] AS [l1.OneToOne_Required_FK10] ON [l10].[Id] = [l1.OneToOne_Required_FK10].[Level1_Required_Id] + LEFT JOIN [LevelThree] AS [l1.OneToOne_Required_FK1.OneToOne_Optional_FK20] ON [l1.OneToOne_Required_FK10].[Id] = [l1.OneToOne_Required_FK1.OneToOne_Optional_FK20].[Level2_Optional_Id] + LEFT JOIN [LevelFour] AS [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required30] ON [l1.OneToOne_Required_FK1.OneToOne_Optional_FK20].[Id] = [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required30].[OneToMany_Required_Inverse4Id] + LEFT JOIN [LevelThree] AS [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3.OneToMany_Optional_Inverse40] ON [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required30].[OneToMany_Optional_Inverse4Id] = [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3.OneToMany_Optional_Inverse40].[Id] + INNER JOIN ( + SELECT [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self20].* + FROM [LevelFour] AS [l41] + LEFT JOIN [LevelThree] AS [l4.OneToOne_Required_FK_Inverse41] ON [l41].[Level3_Required_Id] = [l4.OneToOne_Required_FK_Inverse41].[Id] + LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse30] ON [l4.OneToOne_Required_FK_Inverse41].[Level2_Optional_Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse30].[Id] + LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self20] ON [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse30].[Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Optional_FK_Inverse3.OneToMany_Required_Self20].[OneToMany_Required_Self_Inverse2Id] + ) AS [t1] ON [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required30].[Id] = [t1].[Id] + LEFT JOIN [LevelThree] AS [l2.OneToOne_Optional_FK20] ON [t1].[Id] = [l2.OneToOne_Optional_FK20].[Level2_Optional_Id] + LEFT JOIN ( + SELECT [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3.OneToMany_Required20].* + FROM [LevelFour] AS [l42] + LEFT JOIN [LevelThree] AS [l4.OneToOne_Required_FK_Inverse42] ON [l42].[Level3_Required_Id] = [l4.OneToOne_Required_FK_Inverse42].[Id] + LEFT JOIN [LevelTwo] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse30] ON [l4.OneToOne_Required_FK_Inverse42].[Level2_Required_Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse30].[Id] + LEFT JOIN [LevelThree] AS [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3.OneToMany_Required20] ON [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse30].[Id] = [l4.OneToOne_Required_FK_Inverse4.OneToOne_Required_FK_Inverse3.OneToMany_Required20].[OneToMany_Required_Inverse3Id] + ) AS [t2] ON [t1].[Id] = [t2].[Id] + LEFT JOIN [LevelTwo] AS [l3.OneToOne_Optional_FK_Inverse30] ON [t2].[Level2_Optional_Id] = [l3.OneToOne_Optional_FK_Inverse30].[Id] + LEFT JOIN [LevelThree] AS [l3.OneToOne_Optional_FK_Inverse3.OneToOne_Required_FK20] ON [l3.OneToOne_Optional_FK_Inverse30].[Id] = [l3.OneToOne_Optional_FK_Inverse3.OneToOne_Required_FK20].[Level2_Required_Id] + WHERE ([l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3.OneToMany_Optional_Inverse40].[Name] <> N'Foo') OR [l1.OneToOne_Required_FK1.OneToOne_Optional_FK2.OneToMany_Required3.OneToMany_Optional_Inverse40].[Name] IS NULL +) AS [t3] ON [l2.OneToMany_Optional_Self2].[OneToMany_Optional_Self_Inverse2Id] = [t3].[Id0] +WHERE [l2.OneToMany_Optional_Self2].[Id] <> 42 +ORDER BY [t3].[Id], [t3].[Id0]"); } public override async Task Multiple_SelectMany_with_navigation_and_explicit_DefaultIfEmpty(bool isAsync) { await base.Multiple_SelectMany_with_navigation_and_explicit_DefaultIfEmpty(isAsync); - // issue #15081 -// AssertSql( -// @"SELECT [l1].[Id], [l1].[Date], [l1].[Name], [l1].[OneToMany_Optional_Self_Inverse1Id], [l1].[OneToMany_Required_Self_Inverse1Id], [l1].[OneToOne_Optional_Self1Id] -//FROM [LevelOne] AS [l1] -//INNER JOIN [LevelTwo] AS [l1.OneToMany_Optional1] ON [l1].[Id] = [l1.OneToMany_Optional1].[OneToMany_Optional_Inverse2Id] -//LEFT JOIN ( -// SELECT [l1.OneToMany_Optional1.OneToMany_Optional2].* -// FROM [LevelThree] AS [l1.OneToMany_Optional1.OneToMany_Optional2] -// WHERE [l1.OneToMany_Optional1.OneToMany_Optional2].[Id] > 5 -//) AS [t] ON [l1.OneToMany_Optional1].[Id] = [t].[OneToMany_Optional_Inverse3Id] -//WHERE [t].[Id] IS NOT NULL"); + AssertSql( + @"SELECT [l1].[Id], [l1].[Date], [l1].[Name], [l1].[OneToMany_Optional_Self_Inverse1Id], [l1].[OneToMany_Required_Self_Inverse1Id], [l1].[OneToOne_Optional_Self1Id] +FROM [LevelOne] AS [l1] +INNER JOIN [LevelTwo] AS [l1.OneToMany_Optional1] ON [l1].[Id] = [l1.OneToMany_Optional1].[OneToMany_Optional_Inverse2Id] +LEFT JOIN ( + SELECT [l1.OneToMany_Optional1.OneToMany_Optional2].* + FROM [LevelThree] AS [l1.OneToMany_Optional1.OneToMany_Optional2] + WHERE [l1.OneToMany_Optional1.OneToMany_Optional2].[Id] > 5 +) AS [t] ON [l1.OneToMany_Optional1].[Id] = [t].[OneToMany_Optional_Inverse3Id] +WHERE [t].[Id] IS NOT NULL"); } public override async Task SelectMany_with_navigation_filter_paging_and_explicit_DefaultIfEmpty(bool isAsync) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsWeakQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsWeakQuerySqlServerTest.cs index bbd3cdf8cd6..92d03f5fad1 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsWeakQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexNavigationsWeakQuerySqlServerTest.cs @@ -178,22 +178,11 @@ public override async Task SelectMany_with_Include1(bool isAsync) await base.SelectMany_with_Include1(isAsync); AssertSql( - @"SELECT [l1.OneToMany_Optional1].[Id], [l1.OneToMany_Optional1].[OneToOne_Required_PK_Date], [l1.OneToMany_Optional1].[Level1_Optional_Id], [l1.OneToMany_Optional1].[Level1_Required_Id], [l1.OneToMany_Optional1].[Level2_Name], [l1.OneToMany_Optional1].[OneToMany_Optional_Inverse2Id], [l1.OneToMany_Optional1].[OneToMany_Required_Inverse2Id], [l1.OneToMany_Optional1].[OneToOne_Optional_PK_Inverse2Id] -FROM [Level1] AS [l1] -INNER JOIN [Level1] AS [l1.OneToMany_Optional1] ON [l1].[Id] = [l1.OneToMany_Optional1].[OneToMany_Optional_Inverse2Id] -WHERE [l1.OneToMany_Optional1].[OneToMany_Required_Inverse2Id] IS NOT NULL AND ([l1.OneToMany_Optional1].[Level1_Required_Id] IS NOT NULL AND [l1.OneToMany_Optional1].[OneToOne_Required_PK_Date] IS NOT NULL) -ORDER BY [l1.OneToMany_Optional1].[Id]", - // - @"SELECT [l1.OneToMany_Optional1.OneToMany_Optional2].[Id], [l1.OneToMany_Optional1.OneToMany_Optional2].[Level2_Optional_Id], [l1.OneToMany_Optional1.OneToMany_Optional2].[Level2_Required_Id], [l1.OneToMany_Optional1.OneToMany_Optional2].[Level3_Name], [l1.OneToMany_Optional1.OneToMany_Optional2].[OneToMany_Optional_Inverse3Id], [l1.OneToMany_Optional1.OneToMany_Optional2].[OneToMany_Required_Inverse3Id], [l1.OneToMany_Optional1.OneToMany_Optional2].[OneToOne_Optional_PK_Inverse3Id] -FROM [Level1] AS [l1.OneToMany_Optional1.OneToMany_Optional2] -INNER JOIN ( - SELECT DISTINCT [l1.OneToMany_Optional10].[Id] - FROM [Level1] AS [l10] - INNER JOIN [Level1] AS [l1.OneToMany_Optional10] ON [l10].[Id] = [l1.OneToMany_Optional10].[OneToMany_Optional_Inverse2Id] - WHERE [l1.OneToMany_Optional10].[OneToMany_Required_Inverse2Id] IS NOT NULL AND ([l1.OneToMany_Optional10].[Level1_Required_Id] IS NOT NULL AND [l1.OneToMany_Optional10].[OneToOne_Required_PK_Date] IS NOT NULL) -) AS [t] ON [l1.OneToMany_Optional1.OneToMany_Optional2].[OneToMany_Optional_Inverse3Id] = [t].[Id] -WHERE ([l1.OneToMany_Optional1.OneToMany_Optional2].[OneToMany_Required_Inverse2Id] IS NOT NULL AND ([l1.OneToMany_Optional1.OneToMany_Optional2].[Level1_Required_Id] IS NOT NULL AND [l1.OneToMany_Optional1.OneToMany_Optional2].[OneToOne_Required_PK_Date] IS NOT NULL)) AND ([l1.OneToMany_Optional1.OneToMany_Optional2].[OneToMany_Required_Inverse3Id] IS NOT NULL AND [l1.OneToMany_Optional1.OneToMany_Optional2].[Level2_Required_Id] IS NOT NULL) -ORDER BY [t].[Id]"); + @"SELECT [l].[Id], [l].[OneToOne_Required_PK_Date], [l].[Level1_Optional_Id], [l].[Level1_Required_Id], [l].[Level2_Name], [l].[OneToMany_Optional_Inverse2Id], [l].[OneToMany_Required_Inverse2Id], [l].[OneToOne_Optional_PK_Inverse2Id], [l0].[Id], [l1].[Id], [l1].[Level2_Optional_Id], [l1].[Level2_Required_Id], [l1].[Level3_Name], [l1].[OneToMany_Optional_Inverse3Id], [l1].[OneToMany_Required_Inverse3Id], [l1].[OneToOne_Optional_PK_Inverse3Id] +FROM [Level1] AS [l0] +INNER JOIN [Level1] AS [l] ON [l0].[Id] = [l].[OneToMany_Optional_Inverse2Id] +LEFT JOIN [Level1] AS [l1] ON [l].[Id] = [l1].[OneToMany_Optional_Inverse3Id] +ORDER BY [l0].[Id], [l].[Id], [l1].[Id]"); } private void AssertSql(params string[] expected) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs index 9eed584c654..e65551f24cf 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs @@ -3678,16 +3678,16 @@ public override void Navigation_access_fk_on_derived_entity_using_cast() { base.Navigation_access_fk_on_derived_entity_using_cast(); - // AssertSql( - // @"SELECT [f].[Name] AS [Name0], [t].[Name] AS [CommanderName] - //FROM [ConditionalFactions] AS [f] - //LEFT JOIN ( - // SELECT [f.Commander].* - // FROM [LocustLeaders] AS [f.Commander] - // WHERE [f.Commander].[Discriminator] = N'LocustCommander' - //) AS [t] ON ([f].[Discriminator] = N'LocustHorde') AND ([f].[CommanderName] = [t].[Name]) - //WHERE ([f].[Discriminator] = N'LocustHorde') AND ([f].[Discriminator] = N'LocustHorde') - //ORDER BY [Name0]"); + AssertSql( + @"SELECT [f].[Name], [t].[Name] AS [CommanderName] +FROM [Factions] AS [f] +LEFT JOIN ( + SELECT [l].[Name], [l].[Discriminator], [l].[LocustHordeId], [l].[ThreatLevel], [l].[DefeatedByNickname], [l].[DefeatedBySquadId], [l].[HighCommandId] + FROM [LocustLeaders] AS [l] + WHERE [l].[Discriminator] = N'LocustCommander' +) AS [t] ON [f].[CommanderName] = [t].[Name] +WHERE ([f].[Discriminator] = N'LocustHorde') AND ([f].[Discriminator] = N'LocustHorde') +ORDER BY [f].[Name]"); } public override void Collection_navigation_access_on_derived_entity_using_cast() @@ -3697,10 +3697,9 @@ public override void Collection_navigation_access_on_derived_entity_using_cast() AssertSql( @"SELECT [f].[Name], ( SELECT COUNT(*) - FROM [LocustLeaders] AS [ll] - WHERE [ll].[Discriminator] IN (N'LocustCommander', N'LocustLeader') AND ([f].[Id] = [ll].[LocustHordeId]) -) AS [LeadersCount] -FROM [ConditionalFactions] AS [f] + FROM [LocustLeaders] AS [l] + WHERE [l].[Discriminator] IN (N'LocustLeader', N'LocustCommander') AND (([f].[Id] = [l].[LocustHordeId]) AND [l].[LocustHordeId] IS NOT NULL)) AS [LeadersCount] +FROM [Factions] AS [f] WHERE ([f].[Discriminator] = N'LocustHorde') AND ([f].[Discriminator] = N'LocustHorde') ORDER BY [f].[Name]"); } @@ -3709,20 +3708,16 @@ public override void Collection_navigation_access_on_derived_entity_using_cast_i { base.Collection_navigation_access_on_derived_entity_using_cast_in_SelectMany(); - // TODO: this will later be translated to INNER JOIN - // AssertSql( - // @"SELECT [f].[Name] AS [Name0], [f.Leaders].[Name] AS [LeaderName] - //FROM [ConditionalFactions] AS [f] - //INNER JOIN [LocustLeaders] AS [f.Leaders] ON [f].[Id] = [f.Leaders].[LocustHordeId] - //WHERE (([f].[Discriminator] = N'LocustHorde') AND ([f].[Discriminator] = N'LocustHorde')) AND [f.Leaders].[Discriminator] IN (N'LocustCommander', N'LocustLeader') - //ORDER BY [LeaderName]"); - AssertSql( - @"SELECT [f].[Name] AS [Name0], [ll].[Name] AS [LeaderName] -FROM [ConditionalFactions] AS [f] -CROSS JOIN [LocustLeaders] AS [ll] -WHERE (([f].[Discriminator] = N'LocustHorde') AND ([f].[Discriminator] = N'LocustHorde')) AND ([f].[Id] = [ll].[LocustHordeId]) -ORDER BY [LeaderName]"); + @"SELECT [f].[Name], [t].[Name] AS [LeaderName] +FROM [Factions] AS [f] +INNER JOIN ( + SELECT [l].[Name], [l].[Discriminator], [l].[LocustHordeId], [l].[ThreatLevel], [l].[DefeatedByNickname], [l].[DefeatedBySquadId], [l].[HighCommandId] + FROM [LocustLeaders] AS [l] + WHERE [l].[Discriminator] IN (N'LocustLeader', N'LocustCommander') +) AS [t] ON [f].[Id] = [t].[LocustHordeId] +WHERE ([f].[Discriminator] = N'LocustHorde') AND ([f].[Discriminator] = N'LocustHorde') +ORDER BY [t].[Name]"); } public override void Include_on_derived_entity_using_OfType() @@ -3862,7 +3857,7 @@ public override void Cast_result_operator_on_subquery_is_properly_lifted_to_a_co AssertSql( @"SELECT [f].[Eradicated] -FROM [ConditionalFactions] AS [f] +FROM [Factions] AS [f] WHERE [f].[Discriminator] = N'LocustHorde'"); } @@ -3871,11 +3866,19 @@ public override void Comparing_two_collection_navigations_composite_key() base.Comparing_two_collection_navigations_composite_key(); AssertSql( - @"SELECT [g1].[Nickname] AS [Nickname1], [g2].[Nickname] AS [Nickname2] -FROM [Gears] AS [g1] -CROSS JOIN [Gears] AS [g2] -WHERE [g1].[Discriminator] IN (N'Officer', N'Gear') AND (([g1].[Nickname] = [g2].[Nickname]) AND ([g1].[SquadId] = [g2].[SquadId])) -ORDER BY [Nickname1]"); + @"SELECT [t].[Nickname] AS [Nickname1], [t0].[Nickname] AS [Nickname2] +FROM ( + SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] + FROM [Gears] AS [g] + WHERE [g].[Discriminator] IN (N'Gear', N'Officer') +) AS [t] +CROSS JOIN ( + SELECT [g0].[Nickname], [g0].[SquadId], [g0].[AssignedCityName], [g0].[CityOrBirthName], [g0].[Discriminator], [g0].[FullName], [g0].[HasSoulPatch], [g0].[LeaderNickname], [g0].[LeaderSquadId], [g0].[Rank] + FROM [Gears] AS [g0] + WHERE [g0].[Discriminator] IN (N'Gear', N'Officer') +) AS [t0] +WHERE ([t].[Nickname] = [t0].[Nickname]) AND ([t].[SquadId] = [t0].[SquadId]) +ORDER BY [t].[Nickname]"); } public override void Comparing_two_collection_navigations_inheritance() @@ -4494,7 +4497,7 @@ public override async Task Correlated_collections_basic_projecting_single_proper await base.Correlated_collections_basic_projecting_single_property(isAsync); AssertSql( - @"SELECT [g].[Nickname], [g].[SquadId], [t].[Name], [t].[Id], [t].[OwnerFullName] + @"SELECT [g].[Nickname], [g].[SquadId], [t].[Name], [t].[Id] FROM [Gears] AS [g] LEFT JOIN ( SELECT [w].[Name], [w].[Id], [w].[OwnerFullName] @@ -4510,7 +4513,7 @@ public override async Task Correlated_collections_basic_projecting_constant(bool await base.Correlated_collections_basic_projecting_constant(isAsync); AssertSql( - @"SELECT [g].[Nickname], [g].[SquadId], [t].[c], [t].[Id], [t].[OwnerFullName] + @"SELECT [g].[Nickname], [g].[SquadId], [t].[c], [t].[Id] FROM [Gears] AS [g] LEFT JOIN ( SELECT N'BFG' AS [c], [w].[Id], [w].[OwnerFullName] @@ -4526,7 +4529,7 @@ public override async Task Correlated_collections_basic_projecting_constant_bool await base.Correlated_collections_basic_projecting_constant_bool(isAsync); AssertSql( - @"SELECT [g].[Nickname], [g].[SquadId], [t].[c], [t].[Id], [t].[OwnerFullName] + @"SELECT [g].[Nickname], [g].[SquadId], [t].[c], [t].[Id] FROM [Gears] AS [g] LEFT JOIN ( SELECT CAST(1 AS bit) AS [c], [w].[Id], [w].[OwnerFullName] @@ -4638,10 +4641,10 @@ public override async Task Correlated_collections_nested_with_custom_ordering(bo await base.Correlated_collections_nested_with_custom_ordering(isAsync); AssertSql( - @"SELECT [g].[FullName], [g].[Nickname], [g].[SquadId], [t0].[FullName], [t0].[Nickname], [t0].[SquadId], [t0].[Id], [t0].[AmmunitionType], [t0].[IsAutomatic], [t0].[Name], [t0].[OwnerFullName], [t0].[SynergyWithId], [t0].[LeaderNickname], [t0].[LeaderSquadId] + @"SELECT [g].[FullName], [g].[Nickname], [g].[SquadId], [t0].[FullName], [t0].[Nickname], [t0].[SquadId], [t0].[Id], [t0].[AmmunitionType], [t0].[IsAutomatic], [t0].[Name], [t0].[OwnerFullName], [t0].[SynergyWithId] FROM [Gears] AS [g] LEFT JOIN ( - SELECT [g0].[FullName], [g0].[Nickname], [g0].[SquadId], [t].[Id], [t].[AmmunitionType], [t].[IsAutomatic], [t].[Name], [t].[OwnerFullName], [t].[SynergyWithId], [g0].[LeaderNickname], [g0].[LeaderSquadId], [g0].[Rank] + SELECT [g0].[FullName], [g0].[Nickname], [g0].[SquadId], [t].[Id], [t].[AmmunitionType], [t].[IsAutomatic], [t].[Name], [t].[OwnerFullName], [t].[SynergyWithId], [g0].[Rank], [g0].[LeaderNickname], [g0].[LeaderSquadId] FROM [Gears] AS [g0] LEFT JOIN ( SELECT [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] @@ -4847,7 +4850,7 @@ public override async Task Correlated_collections_multiple_nested_complex_collec await base.Correlated_collections_multiple_nested_complex_collections(isAsync); AssertSql( - @"SELECT [g].[FullName], [g].[Nickname], [g].[SquadId], [t2].[FullName], [t2].[Nickname], [t2].[SquadId], [t2].[Id], [t2].[Name], [t2].[IsAutomatic], [t2].[Id0], [t2].[OwnerFullName], [t2].[Nickname0], [t2].[HasSoulPatch], [t2].[SquadId0], [t2].[OwnerFullName0], [t2].[LeaderNickname], [t2].[LeaderSquadId], [t4].[Id], [t4].[AmmunitionType], [t4].[IsAutomatic], [t4].[Name], [t4].[OwnerFullName], [t4].[SynergyWithId] + @"SELECT [g].[FullName], [g].[Nickname], [g].[SquadId], [t2].[FullName], [t2].[Nickname], [t2].[SquadId], [t2].[Id], [t2].[Name], [t2].[IsAutomatic], [t2].[Id0], [t2].[Nickname0], [t2].[HasSoulPatch], [t2].[SquadId0], [t4].[Id], [t4].[AmmunitionType], [t4].[IsAutomatic], [t4].[Name], [t4].[OwnerFullName], [t4].[SynergyWithId] FROM [Gears] AS [g] LEFT JOIN [Tags] AS [t5] ON (([g].[Nickname] = [t5].[GearNickName]) AND [t5].[GearNickName] IS NOT NULL) AND (([g].[SquadId] = [t5].[GearSquadId]) AND [t5].[GearSquadId] IS NOT NULL) LEFT JOIN ( @@ -4856,10 +4859,10 @@ FROM [Gears] AS [g4] WHERE [g4].[Discriminator] IN (N'Gear', N'Officer') ) AS [t6] ON (([t5].[GearNickName] = [t6].[Nickname]) AND [t5].[GearNickName] IS NOT NULL) AND (([t5].[GearSquadId] = [t6].[SquadId]) AND [t5].[GearSquadId] IS NOT NULL) LEFT JOIN ( - SELECT [g0].[FullName], [g0].[Nickname], [g0].[SquadId], [t1].[Id], [t1].[Name], [t1].[IsAutomatic], [t1].[Id0], [t1].[OwnerFullName], [t1].[Nickname] AS [Nickname0], [t1].[HasSoulPatch], [t1].[SquadId] AS [SquadId0], [t1].[OwnerFullName0], [g0].[LeaderNickname], [g0].[LeaderSquadId], [g0].[Rank], [t1].[IsAutomatic0] + SELECT [g0].[FullName], [g0].[Nickname], [g0].[SquadId], [t1].[Id], [t1].[Name], [t1].[IsAutomatic], [t1].[Id0], [t1].[Nickname] AS [Nickname0], [t1].[HasSoulPatch], [t1].[SquadId] AS [SquadId0], [g0].[Rank], [t1].[IsAutomatic0], [g0].[LeaderNickname], [g0].[LeaderSquadId] FROM [Gears] AS [g0] LEFT JOIN ( - SELECT [w].[Id], [w0].[Name], [w0].[IsAutomatic], [w0].[Id] AS [Id0], [w0].[OwnerFullName], [t].[Nickname], [t].[HasSoulPatch], [t].[SquadId], [w].[OwnerFullName] AS [OwnerFullName0], [w].[IsAutomatic] AS [IsAutomatic0] + SELECT [w].[Id], [w0].[Name], [w0].[IsAutomatic], [w0].[Id] AS [Id0], [t].[Nickname], [t].[HasSoulPatch], [t].[SquadId], [w].[IsAutomatic] AS [IsAutomatic0], [w].[OwnerFullName] FROM [Weapons] AS [w] LEFT JOIN ( SELECT [g2].[Nickname], [g2].[SquadId], [g2].[AssignedCityName], [g2].[CityOrBirthName], [g2].[Discriminator], [g2].[FullName], [g2].[HasSoulPatch], [g2].[LeaderNickname], [g2].[LeaderSquadId], [g2].[Rank] @@ -4874,7 +4877,7 @@ FROM [Gears] AS [g1] WHERE [g1].[Discriminator] IN (N'Gear', N'Officer') ) AS [t] ON [s].[Id] = [t].[SquadId] WHERE ([w].[Name] <> N'Bar') OR [w].[Name] IS NULL - ) AS [t1] ON [g0].[FullName] = [t1].[OwnerFullName0] + ) AS [t1] ON [g0].[FullName] = [t1].[OwnerFullName] WHERE [g0].[Discriminator] IN (N'Gear', N'Officer') AND ([g0].[FullName] <> N'Foo') ) AS [t2] ON (([g].[Nickname] = [t2].[LeaderNickname]) AND [t2].[LeaderNickname] IS NOT NULL) AND ([g].[SquadId] = [t2].[LeaderSquadId]) LEFT JOIN ( @@ -5156,7 +5159,7 @@ public override async Task Correlated_collections_on_left_join_with_predicate(bo await base.Correlated_collections_on_left_join_with_predicate(isAsync); AssertSql( - @"SELECT [t].[Nickname], [t0].[Id], [w].[Name], [w].[Id], [w].[OwnerFullName] + @"SELECT [t].[Nickname], [t0].[Id], [w].[Name], [w].[Id] FROM [Tags] AS [t0] LEFT JOIN ( SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] @@ -5173,7 +5176,7 @@ public override async Task Correlated_collections_on_left_join_with_null_value(b await base.Correlated_collections_on_left_join_with_null_value(isAsync); AssertSql( - @"SELECT [t].[Id], [w].[Name], [w].[Id], [w].[OwnerFullName] + @"SELECT [t].[Id], [w].[Name], [w].[Id] FROM [Tags] AS [t] LEFT JOIN ( SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] @@ -5189,7 +5192,7 @@ public override async Task Correlated_collections_left_join_with_self_reference( await base.Correlated_collections_left_join_with_self_reference(isAsync); AssertSql( - @"SELECT [t].[Note], [t].[Id], [t0].[FullName], [t0].[Nickname], [t0].[SquadId], [t0].[LeaderNickname], [t0].[LeaderSquadId] + @"SELECT [t].[Note], [t].[Id], [t0].[FullName], [t0].[Nickname], [t0].[SquadId] FROM [Tags] AS [t] LEFT JOIN ( SELECT [g0].[Nickname], [g0].[SquadId], [g0].[AssignedCityName], [g0].[CityOrBirthName], [g0].[Discriminator], [g0].[FullName], [g0].[HasSoulPatch], [g0].[LeaderNickname], [g0].[LeaderSquadId], [g0].[Rank] @@ -5261,7 +5264,7 @@ public override async Task Correlated_collections_complex_scenario1(bool isAsync await base.Correlated_collections_complex_scenario1(isAsync); AssertSql( - @"SELECT [g].[FullName], [g].[Nickname], [g].[SquadId], [t1].[Id], [t1].[Nickname], [t1].[HasSoulPatch], [t1].[SquadId], [t1].[OwnerFullName] + @"SELECT [g].[FullName], [g].[Nickname], [g].[SquadId], [t1].[Id], [t1].[Nickname], [t1].[HasSoulPatch], [t1].[SquadId] FROM [Gears] AS [g] LEFT JOIN ( SELECT [w].[Id], [t].[Nickname], [t].[HasSoulPatch], [t].[SquadId], [w].[OwnerFullName] @@ -5287,10 +5290,10 @@ public override async Task Correlated_collections_complex_scenario2(bool isAsync await base.Correlated_collections_complex_scenario2(isAsync); AssertSql( - @"SELECT [g].[FullName], [g].[Nickname], [g].[SquadId], [t2].[FullName], [t2].[Nickname], [t2].[SquadId], [t2].[Id], [t2].[Nickname0], [t2].[HasSoulPatch], [t2].[SquadId0], [t2].[OwnerFullName], [t2].[LeaderNickname], [t2].[LeaderSquadId] + @"SELECT [g].[FullName], [g].[Nickname], [g].[SquadId], [t2].[FullName], [t2].[Nickname], [t2].[SquadId], [t2].[Id], [t2].[Nickname0], [t2].[HasSoulPatch], [t2].[SquadId0] FROM [Gears] AS [g] LEFT JOIN ( - SELECT [g0].[FullName], [g0].[Nickname], [g0].[SquadId], [t1].[Id], [t1].[Nickname] AS [Nickname0], [t1].[HasSoulPatch], [t1].[SquadId] AS [SquadId0], [t1].[OwnerFullName], [g0].[LeaderNickname], [g0].[LeaderSquadId] + SELECT [g0].[FullName], [g0].[Nickname], [g0].[SquadId], [t1].[Id], [t1].[Nickname] AS [Nickname0], [t1].[HasSoulPatch], [t1].[SquadId] AS [SquadId0], [g0].[LeaderNickname], [g0].[LeaderSquadId] FROM [Gears] AS [g0] LEFT JOIN ( SELECT [w].[Id], [t].[Nickname], [t].[HasSoulPatch], [t].[SquadId], [w].[OwnerFullName] @@ -5318,7 +5321,7 @@ public override async Task Correlated_collections_with_funky_orderby_complex_sce await base.Correlated_collections_with_funky_orderby_complex_scenario1(isAsync); AssertSql( - @"SELECT [g].[FullName], [g].[Nickname], [g].[SquadId], [t1].[Id], [t1].[Nickname], [t1].[HasSoulPatch], [t1].[SquadId], [t1].[OwnerFullName] + @"SELECT [g].[FullName], [g].[Nickname], [g].[SquadId], [t1].[Id], [t1].[Nickname], [t1].[HasSoulPatch], [t1].[SquadId] FROM [Gears] AS [g] LEFT JOIN ( SELECT [w].[Id], [t].[Nickname], [t].[HasSoulPatch], [t].[SquadId], [w].[OwnerFullName] @@ -5344,13 +5347,13 @@ public override async Task Correlated_collections_with_funky_orderby_complex_sce await base.Correlated_collections_with_funky_orderby_complex_scenario2(isAsync); AssertSql( - @"SELECT [g].[FullName], [g].[Nickname], [g].[SquadId], [t2].[FullName], [t2].[Nickname], [t2].[SquadId], [t2].[Id], [t2].[Nickname0], [t2].[HasSoulPatch], [t2].[SquadId0], [t2].[OwnerFullName], [t2].[LeaderNickname], [t2].[LeaderSquadId] + @"SELECT [g].[FullName], [g].[Nickname], [g].[SquadId], [t2].[FullName], [t2].[Nickname], [t2].[SquadId], [t2].[Id], [t2].[Nickname0], [t2].[HasSoulPatch], [t2].[SquadId0] FROM [Gears] AS [g] LEFT JOIN ( - SELECT [g0].[FullName], [g0].[Nickname], [g0].[SquadId], [t1].[Id], [t1].[Nickname] AS [Nickname0], [t1].[HasSoulPatch], [t1].[SquadId] AS [SquadId0], [t1].[OwnerFullName], [g0].[LeaderNickname], [g0].[LeaderSquadId], [g0].[HasSoulPatch] AS [HasSoulPatch0], [t1].[IsAutomatic], [t1].[Name] + SELECT [g0].[FullName], [g0].[Nickname], [g0].[SquadId], [t1].[Id], [t1].[Nickname] AS [Nickname0], [t1].[HasSoulPatch], [t1].[SquadId] AS [SquadId0], [g0].[HasSoulPatch] AS [HasSoulPatch0], [t1].[IsAutomatic], [t1].[Name], [g0].[LeaderNickname], [g0].[LeaderSquadId] FROM [Gears] AS [g0] LEFT JOIN ( - SELECT [w].[Id], [t].[Nickname], [t].[HasSoulPatch], [t].[SquadId], [w].[OwnerFullName], [w].[IsAutomatic], [w].[Name] + SELECT [w].[Id], [t].[Nickname], [t].[HasSoulPatch], [t].[SquadId], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName] FROM [Weapons] AS [w] LEFT JOIN ( SELECT [g2].[Nickname], [g2].[SquadId], [g2].[AssignedCityName], [g2].[CityOrBirthName], [g2].[Discriminator], [g2].[FullName], [g2].[HasSoulPatch], [g2].[LeaderNickname], [g2].[LeaderSquadId], [g2].[Rank] @@ -5375,20 +5378,15 @@ public override void Correlated_collection_with_top_level_FirstOrDefault() base.Correlated_collection_with_top_level_FirstOrDefault(); AssertSql( - @"SELECT TOP(1) [g].[FullName] -FROM [Gears] AS [g] -WHERE [g].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [g].[Nickname], [g].[SquadId], [g].[FullName]", - // - @"SELECT [g.Weapons].[Id], [g.Weapons].[AmmunitionType], [g.Weapons].[IsAutomatic], [g.Weapons].[Name], [g.Weapons].[OwnerFullName], [g.Weapons].[SynergyWithId], [t].[Nickname], [t].[SquadId], [t].[FullName] -FROM [Weapons] AS [g.Weapons] -INNER JOIN ( - SELECT TOP(1) [g0].[Nickname], [g0].[SquadId], [g0].[FullName] - FROM [Gears] AS [g0] - WHERE [g0].[Discriminator] IN (N'Officer', N'Gear') - ORDER BY [g0].[Nickname], [g0].[SquadId], [g0].[FullName] -) AS [t] ON [g.Weapons].[OwnerFullName] = [t].[FullName] -ORDER BY [t].[Nickname], [t].[SquadId], [t].[FullName]"); + @"SELECT [t].[Nickname], [t].[SquadId], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] +FROM ( + SELECT TOP(1) [g].[Nickname], [g].[SquadId], [g].[FullName] + FROM [Gears] AS [g] + WHERE [g].[Discriminator] IN (N'Gear', N'Officer') + ORDER BY [g].[Nickname] +) AS [t] +LEFT JOIN [Weapons] AS [w] ON [t].[FullName] = [w].[OwnerFullName] +ORDER BY [t].[Nickname], [t].[SquadId], [w].[Id]"); } public override async Task Correlated_collection_with_top_level_Count(bool isAsync) @@ -5398,7 +5396,7 @@ public override async Task Correlated_collection_with_top_level_Count(bool isAsy AssertSql( @"SELECT COUNT(*) FROM [Gears] AS [g] -WHERE [g].[Discriminator] IN (N'Officer', N'Gear')"); +WHERE [g].[Discriminator] IN (N'Gear', N'Officer')"); } public override void Correlated_collection_with_top_level_Last_with_orderby_on_outer() @@ -5406,20 +5404,15 @@ public override void Correlated_collection_with_top_level_Last_with_orderby_on_o base.Correlated_collection_with_top_level_Last_with_orderby_on_outer(); AssertSql( - @"SELECT TOP(1) [g].[FullName] -FROM [Gears] AS [g] -WHERE [g].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [g].[FullName], [g].[Nickname] DESC, [g].[SquadId] DESC", - // - @"SELECT [g.Weapons].[Id], [g.Weapons].[AmmunitionType], [g.Weapons].[IsAutomatic], [g.Weapons].[Name], [g.Weapons].[OwnerFullName], [g.Weapons].[SynergyWithId], [t].[FullName], [t].[Nickname], [t].[SquadId] -FROM [Weapons] AS [g.Weapons] -INNER JOIN ( - SELECT TOP(1) [g0].[FullName], [g0].[Nickname], [g0].[SquadId] - FROM [Gears] AS [g0] - WHERE [g0].[Discriminator] IN (N'Officer', N'Gear') - ORDER BY [g0].[FullName], [g0].[Nickname] DESC, [g0].[SquadId] DESC -) AS [t] ON [g.Weapons].[OwnerFullName] = [t].[FullName] -ORDER BY [t].[FullName], [t].[Nickname] DESC, [t].[SquadId] DESC"); + @"SELECT [t].[Nickname], [t].[SquadId], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] +FROM ( + SELECT TOP(1) [g].[Nickname], [g].[SquadId], [g].[FullName] + FROM [Gears] AS [g] + WHERE [g].[Discriminator] IN (N'Gear', N'Officer') + ORDER BY [g].[FullName] +) AS [t] +LEFT JOIN [Weapons] AS [w] ON [t].[FullName] = [w].[OwnerFullName] +ORDER BY [t].[FullName], [t].[Nickname], [t].[SquadId], [w].[Id]"); } public override void Correlated_collection_with_top_level_Last_with_order_by_on_inner() @@ -5427,20 +5420,15 @@ public override void Correlated_collection_with_top_level_Last_with_order_by_on_ base.Correlated_collection_with_top_level_Last_with_order_by_on_inner(); AssertSql( - @"SELECT TOP(1) [g].[FullName] -FROM [Gears] AS [g] -WHERE [g].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [g].[FullName] DESC, [g].[Nickname] DESC, [g].[SquadId] DESC", - // - @"SELECT [g.Weapons].[Id], [g.Weapons].[AmmunitionType], [g.Weapons].[IsAutomatic], [g.Weapons].[Name], [g.Weapons].[OwnerFullName], [g.Weapons].[SynergyWithId], [t].[FullName], [t].[Nickname], [t].[SquadId] -FROM [Weapons] AS [g.Weapons] -INNER JOIN ( - SELECT TOP(1) [g0].[FullName], [g0].[Nickname], [g0].[SquadId] - FROM [Gears] AS [g0] - WHERE [g0].[Discriminator] IN (N'Officer', N'Gear') - ORDER BY [g0].[FullName] DESC, [g0].[Nickname] DESC, [g0].[SquadId] DESC -) AS [t] ON [g.Weapons].[OwnerFullName] = [t].[FullName] -ORDER BY [t].[FullName] DESC, [t].[Nickname] DESC, [t].[SquadId] DESC, [g.Weapons].[Name]"); + @"SELECT [t].[Nickname], [t].[SquadId], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] +FROM ( + SELECT TOP(1) [g].[Nickname], [g].[SquadId], [g].[FullName] + FROM [Gears] AS [g] + WHERE [g].[Discriminator] IN (N'Gear', N'Officer') + ORDER BY [g].[FullName] DESC +) AS [t] +LEFT JOIN [Weapons] AS [w] ON [t].[FullName] = [w].[OwnerFullName] +ORDER BY [t].[FullName] DESC, [t].[Nickname], [t].[SquadId], [w].[Name], [w].[Id]"); } public override void Include_with_group_by_and_last() @@ -6280,7 +6268,7 @@ public override async Task Correlated_collection_order_by_constant(bool isAsync) await base.Correlated_collection_order_by_constant(isAsync); AssertSql( - @"SELECT [g].[Nickname], [g].[SquadId], [w].[Name], [w].[Id], [w].[OwnerFullName] + @"SELECT [g].[Nickname], [g].[SquadId], [w].[Name], [w].[Id] FROM [Gears] AS [g] LEFT JOIN [Weapons] AS [w] ON [g].[FullName] = [w].[OwnerFullName] WHERE [g].[Discriminator] IN (N'Gear', N'Officer') @@ -6515,7 +6503,7 @@ public override async Task Cast_to_derived_type_after_OfType_works(bool isAsync) AssertSql( @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] FROM [Gears] AS [g] -WHERE [g].[Discriminator] = N'Officer'"); +WHERE [g].[Discriminator] IN (N'Gear', N'Officer') AND ([g].[Discriminator] = N'Officer')"); } public override async Task Select_subquery_boolean(bool isAsync) @@ -6799,7 +6787,7 @@ public override async Task Cast_subquery_to_base_type_using_typed_ToList(bool is await base.Cast_subquery_to_base_type_using_typed_ToList(isAsync); AssertSql( - @"SELECT [c].[Name], [t].[CityOrBirthName], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Nickname], [t].[Rank], [t].[SquadId], [t].[AssignedCityName] + @"SELECT [c].[Name], [t].[CityOrBirthName], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Nickname], [t].[Rank], [t].[SquadId] FROM [Cities] AS [c] LEFT JOIN ( SELECT [g].[CityOrBirthName], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Nickname], [g].[Rank], [g].[SquadId], [g].[AssignedCityName] @@ -7045,9 +7033,9 @@ public override async Task GroupBy_Property_Include_Aggregate_with_anonymous_sel AssertSql( @"SELECT [g].[Nickname] AS [Key], COUNT(*) AS [c] FROM [Gears] AS [g] -WHERE [g].[Discriminator] IN (N'Officer', N'Gear') +WHERE [g].[Discriminator] IN (N'Gear', N'Officer') GROUP BY [g].[Nickname] -ORDER BY [Key]"); +ORDER BY [g].[Nickname]"); } public override async Task Group_by_entity_key_with_include_on_that_entity_with_key_in_result_selector(bool isAsync) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/GroupByQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/GroupByQuerySqlServerTest.cs index d7cee1d1ae6..6ebdce2774f 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/GroupByQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/GroupByQuerySqlServerTest.cs @@ -937,10 +937,10 @@ public override async Task SelectMany_GroupBy_Aggregate(bool isAsync) await base.SelectMany_GroupBy_Aggregate(isAsync); AssertSql( - @"SELECT [c.Orders].[EmployeeID] AS [Key], COUNT(*) AS [c] + @"SELECT [o].[EmployeeID] AS [Key], COUNT(*) AS [c] FROM [Customers] AS [c] -INNER JOIN [Orders] AS [c.Orders] ON [c].[CustomerID] = [c.Orders].[CustomerID] -GROUP BY [c.Orders].[EmployeeID]"); +INNER JOIN [Orders] AS [o] ON [c].[CustomerID] = [o].[CustomerID] +GROUP BY [o].[EmployeeID]"); } public override async Task Join_GroupBy_Aggregate(bool isAsync) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/OwnedQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/OwnedQuerySqlServerTest.cs index 4cf024b4811..bf8fe7d1271 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/OwnedQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/OwnedQuerySqlServerTest.cs @@ -215,7 +215,7 @@ public override void Query_when_subquery() AssertSql( @"@__p_0='5' -SELECT [t0].[Id], [t0].[Discriminator], [o0].[Id], [o1].[Id], [o1].[PersonAddress_Country_Name], [o1].[PersonAddress_Country_PlanetId], [o2].[Id], [o3].[Id], [o3].[BranchAddress_Country_Name], [o3].[BranchAddress_Country_PlanetId], [o4].[Id], [o5].[Id], [o5].[LeafBAddress_Country_Name], [o5].[LeafBAddress_Country_PlanetId], [o6].[Id], [o7].[Id], [o7].[LeafAAddress_Country_Name], [o7].[LeafAAddress_Country_PlanetId] +SELECT [t0].[Id], [t0].[Discriminator], [o0].[Id], [o1].[Id], [o1].[PersonAddress_Country_Name], [o1].[PersonAddress_Country_PlanetId], [o2].[Id], [o3].[Id], [o3].[BranchAddress_Country_Name], [o3].[BranchAddress_Country_PlanetId], [o4].[Id], [o5].[Id], [o5].[LeafBAddress_Country_Name], [o5].[LeafBAddress_Country_PlanetId], [o6].[Id], [o7].[Id], [o7].[LeafAAddress_Country_Name], [o7].[LeafAAddress_Country_PlanetId], [o8].[ClientId], [o8].[Id] FROM ( SELECT TOP(@__p_0) [t].[Id], [t].[Discriminator] FROM ( @@ -225,16 +225,17 @@ WHERE [o].[Discriminator] IN (N'OwnedPerson', N'Branch', N'LeafB', N'LeafA') ) AS [t] ORDER BY [t].[Id] ) AS [t0] +LEFT JOIN [OwnedPerson] AS [o9] ON [t0].[Id] = [o9].[Id] LEFT JOIN [OwnedPerson] AS [o0] ON [t0].[Id] = [o0].[Id] -LEFT JOIN [OwnedPerson] AS [o8] ON [t0].[Id] = [o8].[Id] -LEFT JOIN [OwnedPerson] AS [o1] ON [o8].[Id] = [o1].[Id] +LEFT JOIN [OwnedPerson] AS [o1] ON [o0].[Id] = [o1].[Id] LEFT JOIN [OwnedPerson] AS [o2] ON [t0].[Id] = [o2].[Id] LEFT JOIN [OwnedPerson] AS [o3] ON [o2].[Id] = [o3].[Id] LEFT JOIN [OwnedPerson] AS [o4] ON [t0].[Id] = [o4].[Id] LEFT JOIN [OwnedPerson] AS [o5] ON [o4].[Id] = [o5].[Id] LEFT JOIN [OwnedPerson] AS [o6] ON [t0].[Id] = [o6].[Id] LEFT JOIN [OwnedPerson] AS [o7] ON [o6].[Id] = [o7].[Id] -ORDER BY [t0].[Id]"); +LEFT JOIN [Order] AS [o8] ON [t0].[Id] = [o8].[ClientId] +ORDER BY [t0].[Id], [o8].[ClientId], [o8].[Id]"); } public override void Navigation_rewrite_on_owned_reference_projecting_scalar() @@ -325,10 +326,10 @@ public override void SelectMany_on_owned_collection() base.SelectMany_on_owned_collection(); AssertSql( - @"SELECT [p.Orders].[Id], [p.Orders].[ClientId] -FROM [OwnedPerson] AS [p] -INNER JOIN [Order] AS [p.Orders] ON [p].[Id] = [p.Orders].[ClientId] -WHERE [p].[Discriminator] IN (N'LeafB', N'LeafA', N'Branch', N'OwnedPerson')"); + @"SELECT [o].[ClientId], [o].[Id] +FROM [OwnedPerson] AS [o0] +INNER JOIN [Order] AS [o] ON [o0].[Id] = [o].[ClientId] +WHERE [o0].[Discriminator] IN (N'OwnedPerson', N'Branch', N'LeafB', N'LeafA')"); } public override void Navigation_rewrite_on_owned_reference_followed_by_regular_entity() @@ -453,13 +454,13 @@ public override void SelectMany_on_owned_reference_followed_by_regular_entity_an base.SelectMany_on_owned_reference_followed_by_regular_entity_and_collection(); AssertSql( - @"SELECT [p.PersonAddress.Country.Planet.Moons].[Id], [p.PersonAddress.Country.Planet.Moons].[Diameter], [p.PersonAddress.Country.Planet.Moons].[PlanetId] -FROM [OwnedPerson] AS [p] -INNER JOIN [OwnedPerson] AS [p.PersonAddress] ON [p].[Id] = [p.PersonAddress].[Id] -INNER JOIN [OwnedPerson] AS [p.PersonAddress.Country] ON [p.PersonAddress].[Id] = [p.PersonAddress.Country].[Id] -INNER JOIN [Planet] AS [p.PersonAddress.Country.Planet] ON [p.PersonAddress.Country].[PersonAddress_Country_PlanetId] = [p.PersonAddress.Country.Planet].[Id] -INNER JOIN [Moon] AS [p.PersonAddress.Country.Planet.Moons] ON [p.PersonAddress.Country.Planet].[Id] = [p.PersonAddress.Country.Planet.Moons].[PlanetId] -WHERE ([p].[Discriminator] IN (N'LeafB', N'LeafA', N'Branch', N'OwnedPerson') AND [p.PersonAddress].[Discriminator] IN (N'LeafB', N'LeafA', N'Branch', N'OwnedPerson')) AND ([p.PersonAddress.Country].[Discriminator] IN (N'LeafB', N'LeafA', N'Branch', N'OwnedPerson') AND [p.PersonAddress.Country].[PersonAddress_Country_PlanetId] IS NOT NULL)"); + @"SELECT [m].[Id], [m].[Diameter], [m].[PlanetId] +FROM [OwnedPerson] AS [o] +LEFT JOIN [OwnedPerson] AS [o0] ON [o].[Id] = [o0].[Id] +LEFT JOIN [OwnedPerson] AS [o1] ON [o0].[Id] = [o1].[Id] +LEFT JOIN [Planet] AS [p] ON [o1].[PersonAddress_Country_PlanetId] = [p].[Id] +INNER JOIN [Moon] AS [m] ON [p].[Id] = [m].[PlanetId] +WHERE [o].[Discriminator] IN (N'OwnedPerson', N'Branch', N'LeafB', N'LeafA')"); } public override void SelectMany_on_owned_reference_with_entity_in_between_ending_in_owned_collection() @@ -467,14 +468,14 @@ public override void SelectMany_on_owned_reference_with_entity_in_between_ending base.SelectMany_on_owned_reference_with_entity_in_between_ending_in_owned_collection(); AssertSql( - @"SELECT [p.PersonAddress.Country.Planet.Star.Composition].[Id], [p.PersonAddress.Country.Planet.Star.Composition].[Name], [p.PersonAddress.Country.Planet.Star.Composition].[StarId] -FROM [OwnedPerson] AS [p] -INNER JOIN [OwnedPerson] AS [p.PersonAddress] ON [p].[Id] = [p.PersonAddress].[Id] -INNER JOIN [OwnedPerson] AS [p.PersonAddress.Country] ON [p.PersonAddress].[Id] = [p.PersonAddress.Country].[Id] -INNER JOIN [Planet] AS [p.PersonAddress.Country.Planet] ON [p.PersonAddress.Country].[PersonAddress_Country_PlanetId] = [p.PersonAddress.Country.Planet].[Id] -INNER JOIN [Star] AS [p.PersonAddress.Country.Planet.Star] ON [p.PersonAddress.Country.Planet].[StarId] = [p.PersonAddress.Country.Planet.Star].[Id] -INNER JOIN [Element] AS [p.PersonAddress.Country.Planet.Star.Composition] ON [p.PersonAddress.Country.Planet.Star].[Id] = [p.PersonAddress.Country.Planet.Star.Composition].[StarId] -WHERE ([p].[Discriminator] IN (N'LeafB', N'LeafA', N'Branch', N'OwnedPerson') AND [p.PersonAddress].[Discriminator] IN (N'LeafB', N'LeafA', N'Branch', N'OwnedPerson')) AND ([p.PersonAddress.Country].[Discriminator] IN (N'LeafB', N'LeafA', N'Branch', N'OwnedPerson') AND [p.PersonAddress.Country].[PersonAddress_Country_PlanetId] IS NOT NULL)"); + @"SELECT [e].[Id], [e].[Name], [e].[StarId] +FROM [OwnedPerson] AS [o] +LEFT JOIN [OwnedPerson] AS [o0] ON [o].[Id] = [o0].[Id] +LEFT JOIN [OwnedPerson] AS [o1] ON [o0].[Id] = [o1].[Id] +LEFT JOIN [Planet] AS [p] ON [o1].[PersonAddress_Country_PlanetId] = [p].[Id] +LEFT JOIN [Star] AS [s] ON [p].[StarId] = [s].[Id] +INNER JOIN [Element] AS [e] ON [s].[Id] = [e].[StarId] +WHERE [o].[Discriminator] IN (N'OwnedPerson', N'Branch', N'LeafB', N'LeafA')"); } public override void Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference() diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.ResultOperators.cs b/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.ResultOperators.cs index f8dee1defb3..dcaa582dc9e 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.ResultOperators.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.ResultOperators.cs @@ -1087,9 +1087,9 @@ public override void OfType_Select() base.OfType_Select(); AssertSql( - @"SELECT TOP(1) [o.Customer].[City] + @"SELECT TOP(1) [c].[City] FROM [Orders] AS [o] -LEFT JOIN [Customers] AS [o.Customer] ON [o].[CustomerID] = [o.Customer].[CustomerID] +LEFT JOIN [Customers] AS [c] ON [o].[CustomerID] = [c].[CustomerID] ORDER BY [o].[OrderID]"); } @@ -1098,9 +1098,9 @@ public override void OfType_Select_OfType_Select() base.OfType_Select_OfType_Select(); AssertSql( - @"SELECT TOP(1) [o.Customer].[City] + @"SELECT TOP(1) [c].[City] FROM [Orders] AS [o] -LEFT JOIN [Customers] AS [o.Customer] ON [o].[CustomerID] = [o.Customer].[CustomerID] +LEFT JOIN [Customers] AS [c] ON [o].[CustomerID] = [c].[CustomerID] ORDER BY [o].[OrderID]"); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.Select.cs b/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.Select.cs index f435fee7ed4..ebfeccb1794 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.Select.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.Select.cs @@ -324,7 +324,7 @@ public override void Select_nested_collection_multi_level() base.Select_nested_collection_multi_level(); AssertSql( - @"SELECT [c].[CustomerID], [t].[OrderDate], [t].[OrderID], [t].[CustomerID] + @"SELECT [c].[CustomerID], [t].[OrderDate], [t].[OrderID] FROM [Customers] AS [c] LEFT JOIN ( SELECT TOP(3) [o].[OrderDate], [o].[OrderID], [o].[CustomerID] @@ -974,5 +974,37 @@ ELSE CAST(0 AS bit) END, [o].[OrderID], CAST(LEN([o].[CustomerID]) AS int) FROM [Orders] AS [o]"); } + + public override async Task Multiple_select_many_with_predicate(bool isAsync) + { + await base.Multiple_select_many_with_predicate(isAsync); + + AssertSql( + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] +FROM [Customers] AS [c] +INNER JOIN [Orders] AS [o] ON [c].[CustomerID] = [o].[CustomerID] +INNER JOIN [Order Details] AS [o0] ON [o].[OrderID] = [o0].[OrderID] +WHERE CAST([o0].[Discount] AS float) >= 0.25E0"); + } + + public override async Task SelectMany_without_result_selector_naked_collection_navigation(bool isAsync) + { + await base.SelectMany_without_result_selector_naked_collection_navigation(isAsync); + + AssertSql( + @"SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] +FROM [Customers] AS [c] +INNER JOIN [Orders] AS [o] ON [c].[CustomerID] = [o].[CustomerID]"); + } + + public override async Task SelectMany_without_result_selector_collection_navigation_composed(bool isAsync) + { + await base.SelectMany_without_result_selector_collection_navigation_composed(isAsync); + + AssertSql( + @"SELECT [o].[CustomerID] +FROM [Customers] AS [c] +INNER JOIN [Orders] AS [o] ON [c].[CustomerID] = [o].[CustomerID]"); + } } } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.cs index b70b96c36e1..3cd96c7a9e9 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/SimpleQuerySqlServerTest.cs @@ -356,9 +356,9 @@ public override async Task Default_if_empty_top_level(bool isAsync) SELECT NULL AS [empty] ) AS [empty] LEFT JOIN ( - SELECT [c].[EmployeeID], [c].[City], [c].[Country], [c].[FirstName], [c].[ReportsTo], [c].[Title] - FROM [Employees] AS [c] - WHERE [c].[EmployeeID] = -1 + SELECT [e].[EmployeeID], [e].[City], [e].[Country], [e].[FirstName], [e].[ReportsTo], [e].[Title] + FROM [Employees] AS [e] + WHERE [e].[EmployeeID] = -1 ) AS [t] ON 1 = 1"); } @@ -367,7 +367,26 @@ public override async Task Join_with_default_if_empty_on_both_sources(bool isAsy await base.Join_with_default_if_empty_on_both_sources(isAsync); AssertSql( - ""); + @"SELECT [t].[EmployeeID], [t].[City], [t].[Country], [t].[FirstName], [t].[ReportsTo], [t].[Title] +FROM ( + SELECT NULL AS [empty] +) AS [empty] +LEFT JOIN ( + SELECT [e].[EmployeeID], [e].[City], [e].[Country], [e].[FirstName], [e].[ReportsTo], [e].[Title] + FROM [Employees] AS [e] + WHERE [e].[EmployeeID] = -1 +) AS [t] ON 1 = 1 +INNER JOIN ( + SELECT [t0].[EmployeeID], [t0].[City], [t0].[Country], [t0].[FirstName], [t0].[ReportsTo], [t0].[Title], [t0].[EmployeeID] AS [EmployeeID0] + FROM ( + SELECT NULL AS [empty] + ) AS [empty0] + LEFT JOIN ( + SELECT [e0].[EmployeeID], [e0].[City], [e0].[Country], [e0].[FirstName], [e0].[ReportsTo], [e0].[Title] + FROM [Employees] AS [e0] + WHERE [e0].[EmployeeID] = -1 + ) AS [t0] ON 1 = 1 +) AS [t1] ON [t].[EmployeeID] = [t1].[EmployeeID]"); } public override async Task Default_if_empty_top_level_followed_by_projecting_constant(bool isAsync) @@ -375,7 +394,15 @@ public override async Task Default_if_empty_top_level_followed_by_projecting_con await base.Default_if_empty_top_level_followed_by_projecting_constant(isAsync); AssertSql( - ""); + @"SELECT N'Foo' +FROM ( + SELECT NULL AS [empty] +) AS [empty] +LEFT JOIN ( + SELECT [e].[EmployeeID], [e].[City], [e].[Country], [e].[FirstName], [e].[ReportsTo], [e].[Title] + FROM [Employees] AS [e] + WHERE [e].[EmployeeID] = -1 +) AS [t] ON 1 = 1"); } public override async Task Default_if_empty_top_level_positive(bool isAsync) @@ -388,9 +415,9 @@ public override async Task Default_if_empty_top_level_positive(bool isAsync) SELECT NULL AS [empty] ) AS [empty] LEFT JOIN ( - SELECT [c].[EmployeeID], [c].[City], [c].[Country], [c].[FirstName], [c].[ReportsTo], [c].[Title] - FROM [Employees] AS [c] - WHERE [c].[EmployeeID] > 0 + SELECT [e].[EmployeeID], [e].[City], [e].[Country], [e].[FirstName], [e].[ReportsTo], [e].[Title] + FROM [Employees] AS [e] + WHERE [e].[EmployeeID] > 0 ) AS [t] ON 1 = 1"); } @@ -422,7 +449,7 @@ public override async Task Default_if_empty_top_level_projection(bool isAsync) SELECT NULL AS [empty] ) AS [empty] LEFT JOIN ( - SELECT [e].[EmployeeID] + SELECT [e].[EmployeeID], [e].[City], [e].[Country], [e].[FirstName], [e].[ReportsTo], [e].[Title] FROM [Employees] AS [e] WHERE [e].[EmployeeID] = -1 ) AS [t] ON 1 = 1"); @@ -1907,19 +1934,9 @@ public override async Task SelectMany_Joined_DefaultIfEmpty(bool isAsync) await base.SelectMany_Joined_DefaultIfEmpty(isAsync); AssertSql( - @"SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [c].[ContactName] + @"SELECT [c].[ContactName], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] FROM [Customers] AS [c] -CROSS APPLY ( - SELECT [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate] - FROM ( - SELECT NULL AS [empty] - ) AS [empty] - LEFT JOIN ( - SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] - FROM [Orders] AS [o] - WHERE [o].[CustomerID] = [c].[CustomerID] - ) AS [t] ON 1 = 1 -) AS [t0]"); +LEFT JOIN [Orders] AS [o] ON [c].[CustomerID] = [o].[CustomerID]"); } public override async Task SelectMany_Joined_DefaultIfEmpty2(bool isAsync) @@ -1927,19 +1944,9 @@ public override async Task SelectMany_Joined_DefaultIfEmpty2(bool isAsync) await base.SelectMany_Joined_DefaultIfEmpty2(isAsync); AssertSql( - @"SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate] + @"SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] FROM [Customers] AS [c] -CROSS APPLY ( - SELECT [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate] - FROM ( - SELECT NULL AS [empty] - ) AS [empty] - LEFT JOIN ( - SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] - FROM [Orders] AS [o] - WHERE [o].[CustomerID] = [c].[CustomerID] - ) AS [t] ON 1 = 1 -) AS [t0]"); +LEFT JOIN [Orders] AS [o] ON [c].[CustomerID] = [o].[CustomerID]"); } public override async Task SelectMany_Joined_Take(bool isAsync) @@ -1947,13 +1954,12 @@ public override async Task SelectMany_Joined_Take(bool isAsync) await base.SelectMany_Joined_Take(isAsync); AssertSql( - @"SELECT [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate], [c].[ContactName] + @"SELECT [c].[ContactName], [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate] FROM [Customers] AS [c] -CROSS APPLY ( +INNER JOIN ( SELECT TOP(1000) [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] FROM [Orders] AS [o] - WHERE [o].[CustomerID] = [c].[CustomerID] -) AS [t]"); +) AS [t] ON [c].[CustomerID] = [t].[CustomerID]"); } public override async Task Take_with_single(bool isAsync) @@ -2470,14 +2476,27 @@ public override async Task Select_DTO_with_member_init_distinct_in_subquery_tran await base.Select_DTO_with_member_init_distinct_in_subquery_translated_to_server(isAsync); AssertSql( - @"SELECT [t].[Id], [t].[Count], [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] FROM ( - SELECT DISTINCT [o].[CustomerID] AS [Id], [o].[OrderID] AS [Count] + SELECT DISTINCT [o].[CustomerID], [o].[OrderID] FROM [Orders] AS [o] WHERE [o].[OrderID] < 10300 ) AS [t] -CROSS JOIN [Customers] AS [c] -WHERE [c].[CustomerID] = [t].[Id]"); +INNER JOIN [Customers] AS [c] ON [t].[CustomerID] = [c].[CustomerID]"); + } + + public override async Task Select_DTO_with_member_init_distinct_in_subquery_translated_to_server_2(bool isAsync) + { + await base.Select_DTO_with_member_init_distinct_in_subquery_translated_to_server_2(isAsync); + + AssertSql( + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] +FROM ( + SELECT DISTINCT [o].[CustomerID], [o].[OrderID] + FROM [Orders] AS [o] + WHERE [o].[OrderID] < 10300 +) AS [t] +INNER JOIN [Customers] AS [c] ON [t].[CustomerID] = [c].[CustomerID]"); } public override void Select_DTO_with_member_init_distinct_in_subquery_used_in_projection_translated_to_server() @@ -2614,9 +2633,9 @@ public override async Task Select_many_cross_join_same_collection(bool isAsync) await base.Select_many_cross_join_same_collection(isAsync); AssertSql( - @"SELECT [c0].[CustomerID], [c0].[Address], [c0].[City], [c0].[CompanyName], [c0].[ContactName], [c0].[ContactTitle], [c0].[Country], [c0].[Fax], [c0].[Phone], [c0].[PostalCode], [c0].[Region] -FROM [Customers] AS [c] -CROSS JOIN [Customers] AS [c0]"); + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] +FROM [Customers] AS [c0] +CROSS JOIN [Customers] AS [c]"); } public override async Task OrderBy_null_coalesce_operator(bool isAsync) @@ -3441,40 +3460,47 @@ public override void DefaultIfEmpty_without_group_join() base.DefaultIfEmpty_without_group_join(); AssertSql( - @"SELECT [t0].[CustomerID] + @"SELECT [t].[CustomerID] FROM ( - SELECT [t].* - FROM ( - SELECT NULL AS [empty] - ) AS [empty] - LEFT JOIN ( - SELECT [c].* - FROM [Customers] AS [c] - WHERE [c].[City] = N'London' - ) AS [t] ON 1 = 1 -) AS [t0] -WHERE [t0].[CustomerID] IS NOT NULL"); + SELECT NULL AS [empty] +) AS [empty] +LEFT JOIN ( + SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] + FROM [Customers] AS [c] + WHERE ([c].[City] = N'London') AND [c].[City] IS NOT NULL +) AS [t] ON 1 = 1 +WHERE [t].[CustomerID] IS NOT NULL"); } public override async Task DefaultIfEmpty_in_subquery(bool isAsync) { await base.DefaultIfEmpty_in_subquery(isAsync); + AssertSql( + @"SELECT [c].[CustomerID], [o].[OrderID] +FROM [Customers] AS [c] +LEFT JOIN [Orders] AS [o] ON [c].[CustomerID] = [o].[CustomerID] +WHERE [o].[OrderID] IS NOT NULL"); + } + + public override async Task DefaultIfEmpty_in_subquery_not_correlated(bool isAsync) + { + await base.DefaultIfEmpty_in_subquery_not_correlated(isAsync); + AssertSql( @"SELECT [c].[CustomerID], [t0].[OrderID] FROM [Customers] AS [c] -CROSS APPLY ( - SELECT [t].* +CROSS JOIN ( + SELECT [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate], [t].[OrderID] AS [OrderID0] FROM ( SELECT NULL AS [empty] ) AS [empty] LEFT JOIN ( - SELECT [o].* + SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] FROM [Orders] AS [o] - WHERE [o].[CustomerID] = [c].[CustomerID] + WHERE [o].[OrderID] > 15000 ) AS [t] ON 1 = 1 -) AS [t0] -WHERE [t0].[OrderID] IS NOT NULL"); +) AS [t0]"); } public override async Task DefaultIfEmpty_in_subquery_nested(bool isAsync) @@ -3482,32 +3508,26 @@ public override async Task DefaultIfEmpty_in_subquery_nested(bool isAsync) await base.DefaultIfEmpty_in_subquery_nested(isAsync); AssertSql( - @"SELECT [c].[CustomerID], [t0].[OrderID], [t2].[OrderDate] -FROM [Customers] AS [c] -CROSS APPLY ( - SELECT [t].* + @"SELECT [t].[CustomerID], [t1].[OrderID], [o0].[OrderDate] +FROM ( + SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] + FROM [Customers] AS [c] + WHERE ([c].[City] = N'Seattle') AND [c].[City] IS NOT NULL +) AS [t] +CROSS JOIN ( + SELECT [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t0].[OrderID] AS [OrderID0] FROM ( SELECT NULL AS [empty] ) AS [empty] LEFT JOIN ( - SELECT [o].* + SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] FROM [Orders] AS [o] - WHERE [o].[OrderID] > 11000 - ) AS [t] ON 1 = 1 -) AS [t0] -CROSS APPLY ( - SELECT [t1].* - FROM ( - SELECT NULL AS [empty] - ) AS [empty0] - LEFT JOIN ( - SELECT [o0].* - FROM [Orders] AS [o0] - WHERE [o0].[CustomerID] = [c].[CustomerID] - ) AS [t1] ON 1 = 1 -) AS [t2] -WHERE ([c].[City] = N'Seattle') AND ([t0].[OrderID] IS NOT NULL AND [t2].[OrderID] IS NOT NULL) -ORDER BY [OrderID], [t2].[OrderDate]"); + WHERE [o].[OrderID] > 15000 + ) AS [t0] ON 1 = 1 +) AS [t1] +LEFT JOIN [Orders] AS [o0] ON [t].[CustomerID] = [o0].[CustomerID] +WHERE [t1].[OrderID] IS NOT NULL AND [o0].[OrderID] IS NOT NULL +ORDER BY [t1].[OrderID], [o0].[OrderDate]"); } [SqlServerCondition(SqlServerCondition.SupportsOffset)] diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsQuerySqliteTest.cs index 8dd44767a83..b24dad5da83 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexNavigationsQuerySqliteTest.cs @@ -15,89 +15,5 @@ public ComplexNavigationsQuerySqliteTest(ComplexNavigationsQuerySqliteFixture fi // Skip for SQLite. Issue #14935. Cannot eval 'from <>f__AnonymousType100`1 _1 in {from Level2 l2 in value(Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[Microsoft.EntityFrameworkCore.TestModels.ComplexNavigationsModel.Level2]) where ?= (Convert(Property([l1], \"Id\"), Nullable`1) == Property([l2], \"OneToMany_Optional_Inverse2Id\")) =? select new <>f__AnonymousType100`1(Name = [l2].Name)}' public override Task SelectMany_subquery_with_custom_projection(bool isAsync) => null; - - [ConditionalTheory(Skip = "issue #15081")] - public override Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany2(bool isAsync) - { - return base.SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany2(isAsync); - } - - [ConditionalTheory(Skip = "issue #15081")] - public override Task Multiple_SelectMany_with_navigation_and_explicit_DefaultIfEmpty(bool isAsync) - { - return base.Multiple_SelectMany_with_navigation_and_explicit_DefaultIfEmpty(isAsync); - } - - [ConditionalTheory(Skip = "issue #15081")] - public override Task Multiple_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_joined_together(bool isAsync) - { - return base.Multiple_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_joined_together(isAsync); - } - - [ConditionalTheory(Skip = "issue #15081")] - public override Task SelectMany_with_navigation_and_explicit_DefaultIfEmpty(bool isAsync) - { - return base.SelectMany_with_navigation_and_explicit_DefaultIfEmpty(isAsync); - } - - [ConditionalTheory(Skip = "issue #15081")] - public override Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany(bool isAsync) - { - return base.SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany(isAsync); - } - - [ConditionalTheory(Skip = "issue #15081")] - public override Task SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_followed_by_Select_required_navigation_using_same_navs(bool isAsync) - { - return base.SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_followed_by_Select_required_navigation_using_same_navs(isAsync); - } - - [ConditionalTheory(Skip = "issue #15081")] - public override Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany3(bool isAsync) - { - return base.SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany3(isAsync); - } - - [ConditionalTheory(Skip = "issue #15081")] - public override Task SelectMany_with_nested_navigation_filter_and_explicit_DefaultIfEmpty(bool isAsync) - { - return base.SelectMany_with_nested_navigation_filter_and_explicit_DefaultIfEmpty(isAsync); - } - - [ConditionalTheory(Skip = "issue #15081")] - public override Task SelectMany_with_nested_navigation_and_explicit_DefaultIfEmpty(bool isAsync) - { - return base.SelectMany_with_nested_navigation_and_explicit_DefaultIfEmpty(isAsync); - } - - [ConditionalTheory(Skip = "issue #15081")] - public override Task SelectMany_with_navigation_filter_and_explicit_DefaultIfEmpty(bool isAsync) - { - return base.SelectMany_with_navigation_filter_and_explicit_DefaultIfEmpty(isAsync); - } - - [ConditionalTheory(Skip = "issue #15081")] - public override Task SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_followed_by_Select_required_navigation_using_different_navs(bool isAsync) - { - return base.SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_followed_by_Select_required_navigation_using_different_navs(isAsync); - } - - [ConditionalTheory(Skip = "issue #15081")] - public override Task SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany4(bool isAsync) - { - return base.SelectMany_with_nested_navigations_explicit_DefaultIfEmpty_and_additional_joins_outside_of_SelectMany4(isAsync); - } - - [ConditionalTheory(Skip = "issue #15081")] - public override Task SelectMany_with_nested_required_navigation_filter_and_explicit_DefaultIfEmpty(bool isAsync) - { - return base.SelectMany_with_nested_required_navigation_filter_and_explicit_DefaultIfEmpty(isAsync); - } - - [ConditionalTheory(Skip = "issue #15081")] - public override Task Complex_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_with_other_query_operators_composed_on_top(bool isAsync) - { - return base.Complex_SelectMany_with_nested_navigations_and_explicit_DefaultIfEmpty_with_other_query_operators_composed_on_top(isAsync); - } } }