diff --git a/src/EFCore.Relational/Query/Pipeline/AsyncQueryingEnumerable.cs b/src/EFCore.Relational/Query/Pipeline/AsyncQueryingEnumerable.cs index f347778fb19..4cd1ef79f98 100644 --- a/src/EFCore.Relational/Query/Pipeline/AsyncQueryingEnumerable.cs +++ b/src/EFCore.Relational/Query/Pipeline/AsyncQueryingEnumerable.cs @@ -20,7 +20,7 @@ private class AsyncQueryingEnumerable : IAsyncEnumerable { private readonly RelationalQueryContext _relationalQueryContext; private readonly SelectExpression _selectExpression; - private readonly Func _shaper; + private readonly Func _shaper; private readonly IQuerySqlGeneratorFactory _querySqlGeneratorFactory; private readonly Type _contextType; private readonly IDiagnosticsLogger _logger; @@ -33,7 +33,7 @@ public AsyncQueryingEnumerable( ISqlExpressionFactory sqlExpressionFactory, IParameterNameGeneratorFactory parameterNameGeneratorFactory, SelectExpression selectExpression, - Func shaper, + Func shaper, Type contextType, IDiagnosticsLogger logger) { @@ -57,7 +57,7 @@ private sealed class AsyncEnumerator : IAsyncEnumerator private ResultCoordinator _resultCoordinator; private readonly RelationalQueryContext _relationalQueryContext; private readonly SelectExpression _selectExpression; - private readonly Func _shaper; + private readonly Func _shaper; private readonly IQuerySqlGeneratorFactory _querySqlGeneratorFactory; private readonly Type _contextType; private readonly IDiagnosticsLogger _logger; @@ -136,13 +136,29 @@ public async ValueTask MoveNextAsync() _resultCoordinator = new ResultCoordinator(); } - var hasNext = _resultCoordinator.HasNext ?? await _dataReader.ReadAsync(_cancellationToken); - _resultCoordinator.HasNext = null; + var hasNext = _resultCoordinator.HasNext ?? await _dataReader.ReadAsync(); + Current = default; - Current - = hasNext - ? _shaper(_relationalQueryContext, _dataReader.DbDataReader, _indexMap, _resultCoordinator) - : default; + if (hasNext) + { + while (true) + { + _resultCoordinator.ResultReady = true; + _resultCoordinator.HasNext = null; + Current = _shaper(_relationalQueryContext, _dataReader.DbDataReader, Current, _indexMap, _resultCoordinator); + if (_resultCoordinator.ResultReady) + { + break; + } + + if (!await _dataReader.ReadAsync()) + { + _resultCoordinator.HasNext = false; + + break; + } + } + } return hasNext; } diff --git a/src/EFCore.Relational/Query/Pipeline/IncludeCompilingExpressionVisitor.cs b/src/EFCore.Relational/Query/Pipeline/IncludeCompilingExpressionVisitor.cs index 11af88a100a..cc46ed3e7c0 100644 --- a/src/EFCore.Relational/Query/Pipeline/IncludeCompilingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Pipeline/IncludeCompilingExpressionVisitor.cs @@ -4,7 +4,9 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Data.Common; +using System.Diagnostics; using System.Linq; using System.Linq.Expressions; using System.Reflection; @@ -20,13 +22,13 @@ namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline { public partial class RelationalShapedQueryCompilingExpressionVisitor { - private class IncludeCompilingExpressionVisitor : ExpressionVisitor + private class CustomShaperCompilingExpressionVisitor : ExpressionVisitor { private readonly ParameterExpression _dbDataReaderParameter; private readonly ParameterExpression _resultCoordinatorParameter; private readonly bool _tracking; - public IncludeCompilingExpressionVisitor( + public CustomShaperCompilingExpressionVisitor( ParameterExpression dbDataReaderParameter, ParameterExpression resultCoordinatorParameter, bool tracking) @@ -37,82 +39,97 @@ public IncludeCompilingExpressionVisitor( } private static readonly MethodInfo _includeReferenceMethodInfo - = typeof(IncludeCompilingExpressionVisitor).GetTypeInfo() + = typeof(CustomShaperCompilingExpressionVisitor).GetTypeInfo() .GetDeclaredMethod(nameof(IncludeReference)); - private static void IncludeReference( + private static void IncludeReference( QueryContext queryContext, - DbDataReader dbDataReader, TEntity entity, - Func innerShaper, + TIncludedEntity relatedEntity, INavigation navigation, INavigation inverseNavigation, - Action fixup, - bool trackingQuery, - ResultCoordinator resultCoordinator) + Action fixup, + bool trackingQuery) + where TIncludingEntity : TEntity { - var relatedEntity = innerShaper(queryContext, dbDataReader, resultCoordinator); - - if (trackingQuery) + if (entity is TIncludingEntity includingEntity) { - // For non-null relatedEntity StateManager will set the flag - if (ReferenceEquals(relatedEntity, null)) + if (trackingQuery) { - queryContext.StateManager.TryGetEntry(entity).SetIsLoaded(navigation); + // For non-null relatedEntity StateManager will set the flag + if (relatedEntity == null) + { + queryContext.StateManager.TryGetEntry(includingEntity).SetIsLoaded(navigation); + } } - } - else - { - SetIsLoadedNoTracking(entity, navigation); - if (!ReferenceEquals(relatedEntity, null)) + else { - fixup(entity, relatedEntity); - if (inverseNavigation != null && !inverseNavigation.IsCollection()) + SetIsLoadedNoTracking(includingEntity, navigation); + if (relatedEntity is object) { - SetIsLoadedNoTracking(relatedEntity, inverseNavigation); + fixup(includingEntity, relatedEntity); + if (inverseNavigation != null && !inverseNavigation.IsCollection()) + { + SetIsLoadedNoTracking(relatedEntity, inverseNavigation); + } } } } } - private static readonly MethodInfo _includeCollectionMethodInfo - = typeof(IncludeCompilingExpressionVisitor).GetTypeInfo() - .GetDeclaredMethod(nameof(IncludeCollection)); + private static readonly MethodInfo _populateCollectionMethodInfo + = typeof(CustomShaperCompilingExpressionVisitor).GetTypeInfo() + .GetDeclaredMethod(nameof(PopulateCollection)); - private static void IncludeCollection( + private static void PopulateCollection( + int collectionId, QueryContext queryContext, DbDataReader dbDataReader, - TEntity entity, - Func outerKeySelector, - Func innerKeySelector, - Func innerShaper, - INavigation navigation, + Func outerIdentifier, + Func selfIdentifier, + Func innerShaper, INavigation inverseNavigation, - Action fixup, + Action fixup, bool trackingQuery, ResultCoordinator resultCoordinator) { - if (entity is null) + var collectionMaterializationContext = resultCoordinator.Collections[collectionId]; + + var parent = collectionMaterializationContext.Parent; + if (collectionMaterializationContext.Collection is null) { + // Nothing to include since parent was not materialized + return; + } + + var entity = (TIncludingEntity)parent; + + var outerKey = outerIdentifier(queryContext, dbDataReader); + if (!StructuralComparisons.StructuralEqualityComparer.Equals( + outerKey, collectionMaterializationContext.OuterIdentifier)) + { + resultCoordinator.HasNext = true; + return; } - if (trackingQuery) + var innerKey = selfIdentifier(queryContext, dbDataReader); + TIncludedEntity current; + if (StructuralComparisons.StructuralEqualityComparer.Equals( + innerKey, collectionMaterializationContext.SelfIdentifier)) { - queryContext.StateManager.TryGetEntry(entity).SetIsLoaded(navigation); + current = (TIncludedEntity)collectionMaterializationContext.Current; } else { - SetIsLoadedNoTracking(entity, navigation); + current = default; + collectionMaterializationContext.SelfIdentifier = innerKey; } - var innerKey = innerKeySelector(queryContext, dbDataReader); - var outerKey = outerKeySelector(queryContext, dbDataReader); - var relatedEntity = innerShaper(queryContext, dbDataReader, resultCoordinator); - - if (ReferenceEquals(relatedEntity, null)) + var relatedEntity = innerShaper(queryContext, dbDataReader, current, resultCoordinator); + collectionMaterializationContext.UpdateCurrent(relatedEntity); + if (relatedEntity is null) { - navigation.GetCollectionAccessor().GetOrCreate(entity); return; } @@ -125,37 +142,52 @@ private static void IncludeCollection( } } - var hasNext = resultCoordinator.HasNext ?? dbDataReader.Read(); - while (hasNext) - { - resultCoordinator.HasNext = null; - var currentOuterKey = outerKeySelector(queryContext, dbDataReader); - if (!StructuralComparisons.StructuralEqualityComparer.Equals(outerKey, currentOuterKey)) - { - resultCoordinator.HasNext = true; - break; - } + resultCoordinator.ResultReady = false; + } + + private static readonly MethodInfo _initializeCollectionIncludeMethodInfo + = typeof(CustomShaperCompilingExpressionVisitor).GetTypeInfo() + .GetDeclaredMethod(nameof(InitializeCollectionInclude)); - var currentInnerKey = innerKeySelector(queryContext, dbDataReader); - if (StructuralComparisons.StructuralEqualityComparer.Equals(innerKey, currentInnerKey)) + private static void InitializeCollectionInclude( + int collectionId, + QueryContext queryContext, + DbDataReader dbDataReader, + ResultCoordinator resultCoordinator, + TEntity entity, + Func outerIdentifier, + INavigation navigation, + IClrCollectionAccessor clrCollectionAccessor, + bool trackingQuery) + where TIncludingEntity : TEntity + { + object collection = null; + if (entity is TIncludingEntity) + { + // Include case + if (trackingQuery) { - continue; + queryContext.StateManager.TryGetEntry(entity).SetIsLoaded(navigation); } - - relatedEntity = innerShaper(queryContext, dbDataReader, resultCoordinator); - if (!trackingQuery) + else { - fixup(entity, relatedEntity); - if (inverseNavigation != null && !inverseNavigation.IsCollection()) - { - SetIsLoadedNoTracking(relatedEntity, inverseNavigation); - } + SetIsLoadedNoTracking(entity, navigation); } - hasNext = resultCoordinator.HasNext ?? dbDataReader.Read(); + collection = clrCollectionAccessor.GetOrCreate(entity); } - resultCoordinator.HasNext = hasNext; + var outerKey = outerIdentifier(queryContext, dbDataReader); + + var collectionMaterializationContext = new CollectionMaterializationContext(entity, collection, outerKey); + if (resultCoordinator.Collections.Count == collectionId) + { + resultCoordinator.Collections.Add(collectionMaterializationContext); + } + else + { + resultCoordinator.Collections[collectionId] = collectionMaterializationContext; + } } private static void SetIsLoadedNoTracking(object entity, INavigation navigation) @@ -170,72 +202,86 @@ protected override Expression VisitExtension(Expression extensionExpression) { if (extensionExpression is IncludeExpression includeExpression) { - Expression result; + Debug.Assert(!includeExpression.Navigation.IsCollection(), + "Only reference include should be present in tree"); var entityClrType = includeExpression.EntityExpression.Type; + var includingClrType = includeExpression.Navigation.DeclaringEntityType.ClrType; var inverseNavigation = includeExpression.Navigation.FindInverse(); - if (includeExpression.Navigation.IsCollection()) + var relatedEntityClrType = includeExpression.Navigation.GetTargetType().ClrType; + if (includingClrType.IsAssignableFrom(entityClrType)) { - var relatedEntityClrType = includeExpression.NavigationExpression.Type.TryGetSequenceType(); - var collectionShaper = (RelationalCollectionShaperExpression)includeExpression.NavigationExpression; - var innerShaper = Visit(collectionShaper.InnerShaper); - - result = Expression.Call( - _includeCollectionMethodInfo.MakeGenericMethod(entityClrType, relatedEntityClrType), - QueryCompilationContext.QueryContextParameter, - _dbDataReaderParameter, - // We don't need to visit entityExpression since it is supposed to be a parameterExpression only - includeExpression.EntityExpression, - Expression.Constant( - Expression.Lambda( - collectionShaper.OuterKeySelector, - QueryCompilationContext.QueryContextParameter, - _dbDataReaderParameter).Compile()), - Expression.Constant( - Expression.Lambda( - collectionShaper.InnerKeySelector, - QueryCompilationContext.QueryContextParameter, - _dbDataReaderParameter).Compile()), - Expression.Constant( - Expression.Lambda( - innerShaper, - QueryCompilationContext.QueryContextParameter, - _dbDataReaderParameter, - _resultCoordinatorParameter).Compile()), - Expression.Constant(includeExpression.Navigation), - Expression.Constant(inverseNavigation, typeof(INavigation)), - Expression.Constant( - GenerateFixup(entityClrType, relatedEntityClrType, includeExpression.Navigation, inverseNavigation).Compile()), - Expression.Constant(_tracking), - _resultCoordinatorParameter); + includingClrType = entityClrType; } - else + + return Expression.Call( + _includeReferenceMethodInfo.MakeGenericMethod(entityClrType, includingClrType, relatedEntityClrType), + QueryCompilationContext.QueryContextParameter, + // We don't need to visit entityExpression since it is supposed to be a parameterExpression only + includeExpression.EntityExpression, + includeExpression.NavigationExpression, + Expression.Constant(includeExpression.Navigation), + Expression.Constant(inverseNavigation, typeof(INavigation)), + Expression.Constant( + GenerateFixup(includingClrType, relatedEntityClrType, includeExpression.Navigation, inverseNavigation).Compile()), + Expression.Constant(_tracking)); + } + + if (extensionExpression is CollectionInitializingExperssion collectionInitializingExperssion) + { + var entityClrType = collectionInitializingExperssion.Parent.Type; + var includingClrType = collectionInitializingExperssion.Navigation.DeclaringEntityType.ClrType; + if (includingClrType.IsAssignableFrom(entityClrType)) { - var relatedEntityClrType = includeExpression.NavigationExpression.Type; - result = Expression.Call( - _includeReferenceMethodInfo.MakeGenericMethod(entityClrType, relatedEntityClrType), - QueryCompilationContext.QueryContextParameter, - _dbDataReaderParameter, - // We don't need to visit entityExpression since it is supposed to be a parameterExpression only - includeExpression.EntityExpression, - Expression.Constant( - Expression.Lambda( - Visit(includeExpression.NavigationExpression), - QueryCompilationContext.QueryContextParameter, - _dbDataReaderParameter, - _resultCoordinatorParameter).Compile()), - Expression.Constant(includeExpression.Navigation), - Expression.Constant(inverseNavigation, typeof(INavigation)), - Expression.Constant( - GenerateFixup(entityClrType, relatedEntityClrType, includeExpression.Navigation, inverseNavigation).Compile()), - Expression.Constant(_tracking), - _resultCoordinatorParameter); + includingClrType = entityClrType; } - return entityClrType != includeExpression.Navigation.DeclaringEntityType.ClrType - ? Expression.IfThen( - Expression.TypeIs(includeExpression.EntityExpression, includeExpression.Navigation.DeclaringEntityType.ClrType), - result) - : result; + return Expression.Call( + _initializeCollectionIncludeMethodInfo.MakeGenericMethod(entityClrType, includingClrType), + Expression.Constant(collectionInitializingExperssion.CollectionId), + QueryCompilationContext.QueryContextParameter, + _dbDataReaderParameter, + _resultCoordinatorParameter, + collectionInitializingExperssion.Parent, + Expression.Constant( + Expression.Lambda( + collectionInitializingExperssion.OuterIdentifier, + QueryCompilationContext.QueryContextParameter, + _dbDataReaderParameter).Compile()), + Expression.Constant(collectionInitializingExperssion.Navigation), + Expression.Constant(collectionInitializingExperssion.Navigation.GetCollectionAccessor()), + Expression.Constant(_tracking)); + } + + if (extensionExpression is CollectionPopulatingExpression collectionPopulatingExpression) + { + var collectionShaper = collectionPopulatingExpression.Parent; + var entityClrType = collectionShaper.Navigation.DeclaringEntityType.ClrType; + var relatedEntityClrType = collectionShaper.Navigation.GetTargetType().ClrType; + var inverseNavigation = collectionShaper.Navigation.FindInverse(); + var innerShaper = Visit(collectionShaper.InnerShaper); + innerShaper = Expression.Constant(((LambdaExpression)innerShaper).Compile()); + + return Expression.Call( + _populateCollectionMethodInfo.MakeGenericMethod(entityClrType, relatedEntityClrType), + Expression.Constant(collectionShaper.CollectionId), + QueryCompilationContext.QueryContextParameter, + _dbDataReaderParameter, + Expression.Constant( + Expression.Lambda( + collectionShaper.OuterIdentifier, + QueryCompilationContext.QueryContextParameter, + _dbDataReaderParameter).Compile()), + Expression.Constant( + Expression.Lambda( + collectionShaper.SelfIdentifier, + QueryCompilationContext.QueryContextParameter, + _dbDataReaderParameter).Compile()), + innerShaper, + Expression.Constant(inverseNavigation, typeof(INavigation)), + Expression.Constant( + GenerateFixup(entityClrType, relatedEntityClrType, collectionShaper.Navigation, inverseNavigation).Compile()), + Expression.Constant(_tracking), + _resultCoordinatorParameter); } return base.VisitExtension(extensionExpression); diff --git a/src/EFCore.Relational/Query/Pipeline/QueryingEnumerable.cs b/src/EFCore.Relational/Query/Pipeline/QueryingEnumerable.cs index 69806e6746a..e6093f20fce 100644 --- a/src/EFCore.Relational/Query/Pipeline/QueryingEnumerable.cs +++ b/src/EFCore.Relational/Query/Pipeline/QueryingEnumerable.cs @@ -19,7 +19,7 @@ private class QueryingEnumerable : IEnumerable { private readonly RelationalQueryContext _relationalQueryContext; private readonly SelectExpression _selectExpression; - private readonly Func _shaper; + private readonly Func _shaper; private readonly IQuerySqlGeneratorFactory _querySqlGeneratorFactory; private readonly Type _contextType; private readonly IDiagnosticsLogger _logger; @@ -31,7 +31,7 @@ public QueryingEnumerable(RelationalQueryContext relationalQueryContext, ISqlExpressionFactory sqlExpressionFactory, IParameterNameGeneratorFactory parameterNameGeneratorFactory, SelectExpression selectExpression, - Func shaper, + Func shaper, Type contextType, IDiagnosticsLogger logger) { @@ -55,7 +55,7 @@ private sealed class Enumerator : IEnumerator private ResultCoordinator _resultCoordinator; private readonly RelationalQueryContext _relationalQueryContext; private readonly SelectExpression _selectExpression; - private readonly Func _shaper; + private readonly Func _shaper; private readonly IQuerySqlGeneratorFactory _querySqlGeneratorFactory; private readonly Type _contextType; private readonly IDiagnosticsLogger _logger; @@ -132,12 +132,28 @@ public bool MoveNext() } var hasNext = _resultCoordinator.HasNext ?? _dataReader.Read(); - _resultCoordinator.HasNext = null; + Current = default; - Current - = hasNext - ? _shaper(_relationalQueryContext, _dataReader.DbDataReader, _indexMap, _resultCoordinator) - : default; + if (hasNext) + { + while (true) + { + _resultCoordinator.ResultReady = true; + _resultCoordinator.HasNext = null; + Current = _shaper(_relationalQueryContext, _dataReader.DbDataReader, Current, _indexMap, _resultCoordinator); + if (_resultCoordinator.ResultReady) + { + break; + } + + if (!_dataReader.Read()) + { + _resultCoordinator.HasNext = false; + + break; + } + } + } return hasNext; } diff --git a/src/EFCore.Relational/Query/Pipeline/RelationalCollectionShaperExpression.cs b/src/EFCore.Relational/Query/Pipeline/RelationalCollectionShaperExpression.cs index 0086e572905..15898d23f89 100644 --- a/src/EFCore.Relational/Query/Pipeline/RelationalCollectionShaperExpression.cs +++ b/src/EFCore.Relational/Query/Pipeline/RelationalCollectionShaperExpression.cs @@ -1,47 +1,88 @@ // 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.Collections.Generic; using System.Linq.Expressions; using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; +using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Query.Pipeline; namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline { - public class RelationalCollectionShaperExpression : CollectionShaperExpression + public class RelationalCollectionShaperExpression : Expression, IPrintable { public RelationalCollectionShaperExpression( - int collectionIndex, - Expression outerKeySelector, - Expression innerKeySelector, + int collectionId, + Expression parentIdentifier, + Expression outerIdentifier, + Expression selfIdentifier, Expression innerShaper, INavigation navigation) - : base(null, innerShaper, navigation) { - CollectionIndex = collectionIndex; - OuterKeySelector = outerKeySelector; - InnerKeySelector = innerKeySelector; + CollectionId = collectionId; + ParentIdentifier = parentIdentifier; + OuterIdentifier = outerIdentifier; + SelfIdentifier = selfIdentifier; + InnerShaper = innerShaper; + Navigation = navigation; } - public int CollectionIndex { get; } - public Expression OuterKeySelector { get; } - public Expression InnerKeySelector { get; } + public int CollectionId { get; } + public Expression ParentIdentifier { get; } + public Expression OuterIdentifier { get; } + public Expression SelfIdentifier { get; } + public Expression InnerShaper { get; } + public INavigation Navigation { get; } + + public override Type Type => typeof(IEnumerable<>).MakeGenericType(InnerShaper.Type); + public override ExpressionType NodeType => ExpressionType.Extension; protected override Expression VisitChildren(ExpressionVisitor visitor) { // Projection is always null so we do not need to visit it. - var outerKeySelector = visitor.Visit(OuterKeySelector); - var innerKeySelector = visitor.Visit(InnerKeySelector); + var parentIdentifier = visitor.Visit(ParentIdentifier); + var outerIdentifier = visitor.Visit(OuterIdentifier); + var selfIdentifier = visitor.Visit(SelfIdentifier); var innerShaper = visitor.Visit(InnerShaper); - return Update(outerKeySelector, innerKeySelector, innerShaper); + return Update(parentIdentifier, outerIdentifier, selfIdentifier, innerShaper); } public RelationalCollectionShaperExpression Update( - Expression outerKeySelector, Expression innerKeySelector, Expression innerShaper) + Expression parentIdentifier, Expression outerIdentifier, Expression selfIdentifier, Expression innerShaper) { - return outerKeySelector != OuterKeySelector || innerKeySelector != InnerKeySelector || innerShaper != InnerShaper - ? new RelationalCollectionShaperExpression(CollectionIndex, outerKeySelector, innerKeySelector, innerShaper, Navigation) + return parentIdentifier != ParentIdentifier + || outerIdentifier != OuterIdentifier + || selfIdentifier != SelfIdentifier + || innerShaper != InnerShaper + ? new RelationalCollectionShaperExpression( + CollectionId, parentIdentifier, outerIdentifier, selfIdentifier, innerShaper, Navigation) : this; } + + public void Print(ExpressionPrinter expressionPrinter) + { + expressionPrinter.StringBuilder.AppendLine("RelationalCollectionShaper:"); + using (expressionPrinter.StringBuilder.Indent()) + { + expressionPrinter.StringBuilder.AppendLine($"CollectionId: {CollectionId}"); + expressionPrinter.StringBuilder.Append("ParentIdentifier:"); + expressionPrinter.Visit(ParentIdentifier); + expressionPrinter.StringBuilder.AppendLine(); + expressionPrinter.StringBuilder.Append("OuterIdentifier:"); + expressionPrinter.Visit(OuterIdentifier); + expressionPrinter.StringBuilder.AppendLine(); + expressionPrinter.StringBuilder.Append("SelfIdentifier:"); + expressionPrinter.Visit(SelfIdentifier); + expressionPrinter.StringBuilder.AppendLine(); + expressionPrinter.StringBuilder.Append("InnerShaper:"); + expressionPrinter.Visit(InnerShaper); + expressionPrinter.StringBuilder.AppendLine(); + expressionPrinter.StringBuilder.AppendLine($"Navigation: {Navigation.Name}"); + + } + } } } diff --git a/src/EFCore.Relational/Query/Pipeline/RelationalProjectionBindingRemovingExpressionVisitor.cs b/src/EFCore.Relational/Query/Pipeline/RelationalProjectionBindingRemovingExpressionVisitor.cs index 05b384abc43..1c2e302abad 100644 --- a/src/EFCore.Relational/Query/Pipeline/RelationalProjectionBindingRemovingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Pipeline/RelationalProjectionBindingRemovingExpressionVisitor.cs @@ -106,16 +106,6 @@ protected override Expression VisitExtension(Expression extensionExpression) projectionBindingExpression.Type); } - if (extensionExpression is RelationalCollectionShaperExpression relationalCollectionShaperExpression) - { - return new RelationalCollectionShaperExpression( - relationalCollectionShaperExpression.CollectionIndex, - Visit(relationalCollectionShaperExpression.OuterKeySelector), - Visit(relationalCollectionShaperExpression.InnerKeySelector), - Visit(relationalCollectionShaperExpression.InnerShaper), - relationalCollectionShaperExpression.Navigation); - } - return base.VisitExtension(extensionExpression); } diff --git a/src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryCompilingExpressionVisitor.cs b/src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryCompilingExpressionVisitor.cs index b2398f86061..2305f44edeb 100644 --- a/src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryCompilingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryCompilingExpressionVisitor.cs @@ -2,6 +2,7 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Data.Common; using System.Linq; using System.Linq.Expressions; @@ -42,30 +43,33 @@ public RelationalShapedQueryCompilingExpressionVisitor( protected override Expression VisitShapedQueryExpression(ShapedQueryExpression shapedQueryExpression) { - var shaperBody = InjectEntityMaterializer(shapedQueryExpression.ShaperExpression); - var selectExpression = (SelectExpression)shapedQueryExpression.QueryExpression; var dataReaderParameter = Expression.Parameter(typeof(DbDataReader), "dataReader"); - var indexMapParameter = Expression.Parameter(typeof(int[]), "indexMap"); var resultCoordinatorParameter = Expression.Parameter(typeof(ResultCoordinator), "resultCoordinator"); + var indexMapParameter = Expression.Parameter(typeof(int[]), "indexMap"); + + var shaper = new ShaperExpressionProcessingExpressionVisitor( + selectExpression, + dataReaderParameter, + resultCoordinatorParameter, + indexMapParameter) + .Inject(shapedQueryExpression.ShaperExpression); + + shaper = InjectEntityMaterializer(shaper); - shaperBody = new RelationalProjectionBindingRemovingExpressionVisitor(selectExpression, dataReaderParameter) - .Visit(shaperBody); - shaperBody = new IncludeCompilingExpressionVisitor(dataReaderParameter, resultCoordinatorParameter, TrackQueryResults) - .Visit(shaperBody); + shaper = new RelationalProjectionBindingRemovingExpressionVisitor(selectExpression, dataReaderParameter) + .Visit(shaper); + shaper = new CustomShaperCompilingExpressionVisitor( + dataReaderParameter, resultCoordinatorParameter, TrackQueryResults) + .Visit(shaper); if (selectExpression.IsNonComposedFromSql()) { - shaperBody = new IndexMapInjectingExpressionVisitor(indexMapParameter).Visit(shaperBody); + shaper = new IndexMapInjectingExpressionVisitor(indexMapParameter).Visit(shaper); } - var shaperLambda = Expression.Lambda( - shaperBody, - QueryCompilationContext.QueryContextParameter, - dataReaderParameter, - indexMapParameter, - resultCoordinatorParameter); + var shaperLambda = (LambdaExpression)shaper; return Expression.New( (Async @@ -110,8 +114,32 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp private class ResultCoordinator { + public bool ResultReady { get; set; } public bool? HasNext { get; set; } - public object[] KeyValues { get; set; } + public IList Collections { get; } = new List(); + public object[] OuterKeyValues { get; set; } + public object[] InnerKeyValues { get; set; } + } + + private class CollectionMaterializationContext + { + public CollectionMaterializationContext(object parent, object collection, object[] outerIdentifier) + { + Parent = parent; + Collection = collection; + OuterIdentifier = outerIdentifier; + } + + public object Parent { get; } + public object Collection { get; } + public object Current { get; private set; } + public object[] OuterIdentifier { get; } + public object[] SelfIdentifier { get; set; } + + public void UpdateCurrent(object current) + { + Current = current; + } } } } diff --git a/src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryOptimizingExpressionVisitors.cs b/src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryOptimizingExpressionVisitors.cs index 5347bc748e3..90f391d4c82 100644 --- a/src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryOptimizingExpressionVisitors.cs +++ b/src/EFCore.Relational/Query/Pipeline/RelationalShapedQueryOptimizingExpressionVisitors.cs @@ -36,28 +36,26 @@ public override Expression Visit(Expression query) query = new SqlExpressionOptimizingVisitor(SqlExpressionFactory, UseRelationalNulls).Visit(query); query = new NullComparisonTransformingExpressionVisitor().Visit(query); - if (query is ShapedQueryExpression shapedQueryExpression) - { - shapedQueryExpression.ShaperExpression - = new ShaperExpressionProcessingExpressionVisitor((SelectExpression)shapedQueryExpression.QueryExpression) - .Inject(shapedQueryExpression.ShaperExpression); - } - return query; } } public class CollectionJoinApplyingExpressionVisitor : ExpressionVisitor { + private int _collectionId; + protected override Expression VisitExtension(Expression extensionExpression) { if (extensionExpression is CollectionShaperExpression collectionShaperExpression) { + var collectionId = _collectionId++; + var innerShaper = Visit(collectionShaperExpression.InnerShaper); var selectExpression = (SelectExpression)collectionShaperExpression.Projection.QueryExpression; return selectExpression.ApplyCollectionJoin( collectionShaperExpression.Projection.Index.Value, + collectionId, innerShaper, collectionShaperExpression.Navigation); } diff --git a/src/EFCore.Relational/Query/Pipeline/RelationalSqlTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/Pipeline/RelationalSqlTranslatingExpressionVisitor.cs index 2c3e949fe95..95c3dafdbb9 100644 --- a/src/EFCore.Relational/Query/Pipeline/RelationalSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Pipeline/RelationalSqlTranslatingExpressionVisitor.cs @@ -10,6 +10,7 @@ using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; +using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Query.NavigationExpansion; using Microsoft.EntityFrameworkCore.Query.Pipeline; using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; @@ -82,10 +83,12 @@ protected override Expression VisitExtension(Expression node) protected override Expression VisitMember(MemberExpression memberExpression) { - var boundProperty = BindProperty(memberExpression.Expression, memberExpression.Member.GetSimpleMemberName()); - if (boundProperty != null) + if (memberExpression.Expression is EntityShaperExpression + || (memberExpression.Expression is UnaryExpression innerUnaryExpression + && innerUnaryExpression.NodeType == ExpressionType.Convert + && innerUnaryExpression.Operand is EntityShaperExpression)) { - return boundProperty; + return BindProperty(memberExpression.Expression, memberExpression.Member.GetSimpleMemberName()); } var innerExpression = Visit(memberExpression.Expression); @@ -97,20 +100,35 @@ protected override Expression VisitMember(MemberExpression memberExpression) private SqlExpression BindProperty(Expression source, string propertyName) { + Type convertedType = null; if (source is UnaryExpression unaryExpression - && unaryExpression.NodeType == ExpressionType.Convert - && unaryExpression.Type == typeof(object)) + && unaryExpression.NodeType == ExpressionType.Convert) { source = unaryExpression.Operand; + if (unaryExpression.Type != typeof(object)) + { + convertedType = unaryExpression.Type; + } } if (source is EntityShaperExpression entityShaper) { var entityType = entityShaper.EntityType; + if (convertedType != null) + { + entityType = entityType.RootType().GetDerivedTypesInclusive() + .FirstOrDefault(et => et.ClrType == convertedType); + + if (entityType == null) + { + return null; + } + } + return BindProperty(entityShaper, entityType.FindProperty(propertyName)); } - return null; + throw new InvalidOperationException(); } private SqlExpression BindProperty(EntityShaperExpression entityShaper, IProperty property) @@ -230,8 +248,52 @@ private static Expression TryRemoveImplicitConvert(Expression expression) return expression; } + + private Expression ConvertAnonymousObjectEqualityComparison(BinaryExpression binaryExpression) + { + Expression removeObjectConvert(Expression expression) + { + if (expression is UnaryExpression unaryExpression + && expression.Type == typeof(object) + && expression.NodeType == ExpressionType.Convert) + { + return unaryExpression.Operand; + } + + return expression; + } + + var leftExpressions = ((NewArrayExpression)((NewExpression)binaryExpression.Left).Arguments[0]).Expressions; + var rightExpressions = ((NewArrayExpression)((NewExpression)binaryExpression.Right).Arguments[0]).Expressions; + + return leftExpressions.Zip( + rightExpressions, + (l, r) => + { + l = removeObjectConvert(l); + r = removeObjectConvert(r); + if (l.Type.IsNullableType()) + { + r = r.Type.IsNullableType() ? r : Expression.Convert(r, l.Type); + } + else if (r.Type.IsNullableType()) + { + l = l.Type.IsNullableType() ? l : Expression.Convert(l, r.Type); + } + + return Expression.Equal(l, r); + }) + .Aggregate((a, b) => Expression.AndAlso(a, b)); + } + protected override Expression VisitBinary(BinaryExpression binaryExpression) { + if (binaryExpression.Left.Type == typeof(AnonymousObject) + && binaryExpression.NodeType == ExpressionType.Equal) + { + return Visit(ConvertAnonymousObjectEqualityComparison(binaryExpression)); + } + var left = TryRemoveImplicitConvert(binaryExpression.Left); var right = TryRemoveImplicitConvert(binaryExpression.Right); diff --git a/src/EFCore.Relational/Query/Pipeline/ShaperExpressionDedupingExpressionVisitor.cs b/src/EFCore.Relational/Query/Pipeline/ShaperExpressionDedupingExpressionVisitor.cs index df04912f8c3..71150cb1715 100644 --- a/src/EFCore.Relational/Query/Pipeline/ShaperExpressionDedupingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/Pipeline/ShaperExpressionDedupingExpressionVisitor.cs @@ -1,8 +1,14 @@ // 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.Collections.Generic; +using System.Diagnostics; +using System.Linq; using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; +using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Query.NavigationExpansion; using Microsoft.EntityFrameworkCore.Query.Pipeline; using Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions; @@ -12,23 +18,78 @@ namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline public class ShaperExpressionProcessingExpressionVisitor : ExpressionVisitor { private readonly SelectExpression _selectExpression; + private readonly ParameterExpression _dataReaderParameter; + private readonly ParameterExpression _resultCoordinatorParameter; + private readonly ParameterExpression _indexMapParameter; private IDictionary _mapping = new Dictionary(); private List _variables = new List(); private List _expressions = new List(); - private List _collectionIncludes = new List(); + private List _collectionPopulatingExpressions = new List(); - public ShaperExpressionProcessingExpressionVisitor(SelectExpression selectExpression) + public ShaperExpressionProcessingExpressionVisitor( + SelectExpression selectExpression, + ParameterExpression dataReaderParameter, + ParameterExpression resultCoordinatorParameter, + ParameterExpression indexMapParameter) { _selectExpression = selectExpression; + _dataReaderParameter = dataReaderParameter; + _resultCoordinatorParameter = resultCoordinatorParameter; + _indexMapParameter = indexMapParameter; } - public BlockExpression Inject(Expression expression) + public Expression Inject(Expression expression) { var result = Visit(expression); - _expressions.AddRange(_collectionIncludes); - _expressions.Add(result); - return Expression.Block(_variables, _expressions); + if (_collectionPopulatingExpressions.Count > 0) + { + _expressions.Add(result); + result = Expression.Block(_variables, _expressions); + _expressions.Clear(); + _variables.Clear(); + + var resultParameter = Expression.Parameter(result.Type, "result"); + + _expressions.Add( + Expression.IfThen( + Expression.Equal(resultParameter, Expression.Default(result.Type)), + Expression.Assign(resultParameter, result))); + _expressions.AddRange(_collectionPopulatingExpressions); + _expressions.Add(resultParameter); + + return ConvertToLambda(Expression.Block(_expressions), resultParameter); + } + else if (_expressions.All(e => e.NodeType == ExpressionType.Assign)) + { + result = new ReplacingExpressionVisitor(_expressions.Cast() + .ToDictionary(e => e.Left, e => e.Right)).Visit(result); + } + else + { + _expressions.Add(result); + result = Expression.Block(_variables, _expressions); + } + + return ConvertToLambda(result, Expression.Parameter(result.Type, "result")); + } + + private LambdaExpression ConvertToLambda(Expression result, ParameterExpression resultParameter) + { + return _indexMapParameter != null + ? Expression.Lambda( + result, + QueryCompilationContext.QueryContextParameter, + _dataReaderParameter, + resultParameter, + _indexMapParameter, + _resultCoordinatorParameter) + : Expression.Lambda( + result, + QueryCompilationContext.QueryContextParameter, + _dataReaderParameter, + resultParameter, + _resultCoordinatorParameter); } protected override Expression VisitExtension(Expression extensionExpression) @@ -66,20 +127,29 @@ protected override Expression VisitExtension(Expression extensionExpression) var entity = Visit(includeExpression.EntityExpression); if (includeExpression.NavigationExpression is RelationalCollectionShaperExpression relationalCollectionShaperExpression) { - _collectionIncludes.Add(includeExpression.Update( + var innerShaper = new ShaperExpressionProcessingExpressionVisitor( + _selectExpression, _dataReaderParameter, _resultCoordinatorParameter, null) + .Inject(relationalCollectionShaperExpression.InnerShaper); + + _expressions.Add(new CollectionInitializingExperssion( + relationalCollectionShaperExpression.CollectionId, entity, - relationalCollectionShaperExpression.Update( - relationalCollectionShaperExpression.OuterKeySelector, - relationalCollectionShaperExpression.InnerKeySelector, - new ShaperExpressionProcessingExpressionVisitor(_selectExpression) - .Inject(relationalCollectionShaperExpression.InnerShaper)))); + relationalCollectionShaperExpression.OuterIdentifier, + includeExpression.Navigation)); + + _collectionPopulatingExpressions.Add(new CollectionPopulatingExpression( + relationalCollectionShaperExpression.Update( + relationalCollectionShaperExpression.ParentIdentifier, + relationalCollectionShaperExpression.OuterIdentifier, + relationalCollectionShaperExpression.SelfIdentifier, + innerShaper), + true)); } else { _expressions.Add(includeExpression.Update( entity, - new ShaperExpressionProcessingExpressionVisitor(_selectExpression) - .Inject(includeExpression.NavigationExpression))); + Visit(includeExpression.NavigationExpression))); } return entity; @@ -95,4 +165,84 @@ private Expression GenerateKey(ProjectionBindingExpression projectionBindingExpr : projectionBindingExpression; } } + + public class CollectionInitializingExperssion : Expression, IPrintable + { + public CollectionInitializingExperssion(int collectionId, Expression parent, Expression outerIdentifier, INavigation navigation) + { + CollectionId = collectionId; + Parent = parent; + OuterIdentifier = outerIdentifier; + Navigation = navigation; + } + + protected override Expression VisitChildren(ExpressionVisitor visitor) + { + var parent = visitor.Visit(Parent); + var outerIdentifier = visitor.Visit(OuterIdentifier); + + return parent != Parent || outerIdentifier != OuterIdentifier + ? new CollectionInitializingExperssion(CollectionId, parent, outerIdentifier, Navigation) + : this; + } + + public void Print(ExpressionPrinter expressionPrinter) + { + expressionPrinter.StringBuilder.AppendLine("InitializeCollection:"); + using (expressionPrinter.StringBuilder.Indent()) + { + expressionPrinter.StringBuilder.AppendLine($"CollectionId: {CollectionId}"); + expressionPrinter.StringBuilder.AppendLine($"Navigation: {Navigation.Name}"); + expressionPrinter.StringBuilder.Append("Parent:"); + expressionPrinter.Visit(Parent); + expressionPrinter.StringBuilder.AppendLine(); + expressionPrinter.StringBuilder.Append("OuterIdentifier:"); + expressionPrinter.Visit(OuterIdentifier); + expressionPrinter.StringBuilder.AppendLine(); + } + } + + public override Type Type => Navigation.ClrType; + + public override ExpressionType NodeType => ExpressionType.Extension; + + public int CollectionId { get; } + public Expression Parent { get; } + public Expression OuterIdentifier { get; } + public INavigation Navigation { get; } + } + + public class CollectionPopulatingExpression : Expression, IPrintable + { + public CollectionPopulatingExpression(RelationalCollectionShaperExpression parent, bool include) + { + Parent = parent; + Include = include; + } + + protected override Expression VisitChildren(ExpressionVisitor visitor) + { + var parent = (RelationalCollectionShaperExpression)visitor.Visit(Parent); + + return parent != Parent + ? new CollectionPopulatingExpression(parent, Include) + : this; + } + + public void Print(ExpressionPrinter expressionPrinter) + { + expressionPrinter.StringBuilder.AppendLine("PopulateCollection:"); + using (expressionPrinter.StringBuilder.Indent()) + { + expressionPrinter.StringBuilder.Append("Parent:"); + expressionPrinter.Visit(Parent); + } + } + + public override Type Type => typeof(void); + + public override ExpressionType NodeType => ExpressionType.Extension; + public RelationalCollectionShaperExpression Parent { get; } + public bool Include { get; } + } } diff --git a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SelectExpression.cs index d75dd3d3027..c4d7f635d8f 100644 --- a/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SelectExpression.cs +++ b/src/EFCore.Relational/Query/Pipeline/SqlExpressions/SelectExpression.cs @@ -2,20 +2,16 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections; using System.Collections.Generic; -using System.Diagnostics; using System.Linq; using System.Linq.Expressions; using System.Reflection; -using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Query.Internal; using Microsoft.EntityFrameworkCore.Query.Pipeline; -using Microsoft.EntityFrameworkCore.Storage; namespace Microsoft.EntityFrameworkCore.Relational.Query.Pipeline.SqlExpressions { @@ -30,8 +26,7 @@ private readonly IDictionary _orderings = new List(); private readonly List _identifyingProjection = new List(); - private readonly List<(List outerKey, List innerKey, SelectExpression innerSelectExpression)> _pendingCollectionJoins - = new List<(List outerKey, List innerKey, SelectExpression innerSelectExpression)>(); + private readonly List _pendingCollectionJoins = new List(); public IReadOnlyList Projection => _projection; public IReadOnlyList Tables => _tables; @@ -643,10 +638,7 @@ private static bool IsNullableProjection(ProjectionExpression projection) public CollectionShaperExpression AddCollectionProjection(ShapedQueryExpression shapedQueryExpression, INavigation navigation) { var innerSelectExpression = (SelectExpression)shapedQueryExpression.QueryExpression; - _pendingCollectionJoins.Add( - (GetIdentifyingProjection(), - innerSelectExpression.GetIdentifyingProjection(), - innerSelectExpression)); + _pendingCollectionJoins.Add(innerSelectExpression); return new CollectionShaperExpression( new ProjectionBindingExpression(this, _pendingCollectionJoins.Count - 1, typeof(object)), @@ -654,37 +646,33 @@ public CollectionShaperExpression AddCollectionProjection(ShapedQueryExpression navigation); } - public RelationalCollectionShaperExpression ApplyCollectionJoin(int collectionId, Expression shaperExpression, INavigation navigation) + public RelationalCollectionShaperExpression ApplyCollectionJoin( + int collectionIndex, int collectionId, Expression shaperExpression, INavigation navigation) { - var snapshot = _pendingCollectionJoins[collectionId]; - var outerKey = ConvertKeyExpressions(snapshot.outerKey); - var innerSelectExpression = snapshot.innerSelectExpression; + var innerSelectExpression = _pendingCollectionJoins[collectionIndex]; + var outerIdentifier = GetUniqueIdentifier(); innerSelectExpression.ApplyProjection(); - var innerKey = innerSelectExpression.ConvertKeyExpressions(snapshot.innerKey); - var boolTypeMapping = innerSelectExpression.Predicate.TypeMapping; - foreach (var orderingKey in snapshot.outerKey) + var selfIdentifier = innerSelectExpression.GetUniqueIdentifier(); + foreach (var orderingKey in _identifyingProjection) { AppendOrdering(new OrderingExpression(orderingKey, ascending: true)); } - if (collectionId > 0) - { - foreach (var orderingKey in _pendingCollectionJoins[collectionId - 1].innerKey) - { - AppendOrdering(new OrderingExpression(orderingKey, ascending: true)); - } + //_identifyingProjection.AddRange(innerSelectExpression._identifyingProjection); - outerKey = ConvertKeyExpressions(snapshot.outerKey.Concat(_pendingCollectionJoins[collectionId - 1].innerKey).ToList()); - } - - var (outer, inner) = TryExtractJoinKey(innerSelectExpression); - if (outer != null) + var joinPredicate = ExtractJoinKey(innerSelectExpression); + if (joinPredicate != null) { if (IsDistinct || Limit != null || Offset != null) { - outer = new SqlRemappingVisitor(PushdownIntoSubquery()).Remap(outer); + var remappingVisitor = new SqlRemappingVisitor(PushdownIntoSubquery()); + joinPredicate = remappingVisitor.Remap(joinPredicate); + for (var i = collectionIndex + 1; i < _pendingCollectionJoins.Count; i++) + { + _pendingCollectionJoins[i] = remappingVisitor.Remap(_pendingCollectionJoins[i]); + } } if (innerSelectExpression.Offset != null @@ -693,12 +681,11 @@ public RelationalCollectionShaperExpression ApplyCollectionJoin(int collectionId || innerSelectExpression.Predicate != null || innerSelectExpression.Tables.Count > 1) { - inner = new SqlRemappingVisitor(innerSelectExpression.PushdownIntoSubquery()) - .Remap(inner); + joinPredicate = new SqlRemappingVisitor(innerSelectExpression.PushdownIntoSubquery()) + .Remap(joinPredicate); } - var leftJoinExpression = new LeftJoinExpression(innerSelectExpression.Tables.Single(), - new SqlBinaryExpression(ExpressionType.Equal, outer, inner, typeof(bool), boolTypeMapping)); + var leftJoinExpression = new LeftJoinExpression(innerSelectExpression.Tables.Single(), joinPredicate); _tables.Add(leftJoinExpression); var indexOffset = _projection.Count; foreach (var projection in innerSelectExpression.Projection) @@ -713,24 +700,24 @@ public RelationalCollectionShaperExpression ApplyCollectionJoin(int collectionId var shaperRemapper = new ShaperRemappingExpressionVisitor(this, innerSelectExpression, indexOffset); var innerShaper = shaperRemapper.Visit(shaperExpression); - innerKey = shaperRemapper.Visit(innerKey); + selfIdentifier = shaperRemapper.Visit(selfIdentifier); return new RelationalCollectionShaperExpression( collectionId, - outerKey, - innerKey, + null, + outerIdentifier, + selfIdentifier, innerShaper, navigation); - } throw new NotImplementedException(); } - private Expression ConvertKeyExpressions(List keyExpressions) + private Expression GetUniqueIdentifier() { var updatedExpressions = new List(); - foreach (var keyExpression in keyExpressions) + foreach (var keyExpression in _identifyingProjection) { var index = AddToProjection(keyExpression); var projectionBindingExpression = new ProjectionBindingExpression(this, index, keyExpression.Type); @@ -746,11 +733,6 @@ private Expression ConvertKeyExpressions(List keyExpressions) updatedExpressions); } - private List GetIdentifyingProjection() - { - return _identifyingProjection.ToList(); - } - private class ShaperRemappingExpressionVisitor : ExpressionVisitor { private readonly SelectExpression _queryExpression; @@ -801,49 +783,84 @@ private object GetProjectionIndex(ProjectionBindingExpression projectionBindingE } } - private (SqlExpression outer, SqlExpression inner) TryExtractJoinKey(SelectExpression inner) + private SqlExpression ExtractJoinKey(SelectExpression selectExpression) { - if (inner.Predicate is SqlBinaryExpression sqlBinaryExpression) + if (selectExpression.Predicate != null) { - // TODO: Handle composite key case - var keyComparison = ValidateKeyComparison(inner, sqlBinaryExpression); - if (keyComparison.outer != null) + var joinPredicate = ExtractJoinKey(selectExpression, selectExpression.Predicate, out var predicate); + selectExpression.Predicate = predicate; + + return joinPredicate; + } + + return null; + } + + private SqlExpression ExtractJoinKey(SelectExpression selectExpression, SqlExpression predicate, out SqlExpression updatedPredicate) + { + if (predicate is SqlBinaryExpression sqlBinaryExpression) + { + var joinPredicate = ValidateKeyComparison(selectExpression, sqlBinaryExpression); + if (joinPredicate != null) { - inner.Predicate = null; - return keyComparison; + updatedPredicate = null; + + return joinPredicate; + } + + if (sqlBinaryExpression.OperatorType == ExpressionType.AndAlso) + { + static SqlExpression combineNonNullExpressions(SqlExpression left, SqlExpression right) + { + return left != null + ? right != null + ? new SqlBinaryExpression(ExpressionType.AndAlso, left, right, left.Type, left.TypeMapping) + : left + : right; + } + + var leftJoinKey = ExtractJoinKey(selectExpression, sqlBinaryExpression.Left, out var leftPredicate); + var rightJoinKey = ExtractJoinKey(selectExpression, sqlBinaryExpression.Right, out var rightPredicate); + + updatedPredicate = combineNonNullExpressions(leftPredicate, rightPredicate); + + return combineNonNullExpressions(leftJoinKey, rightJoinKey); } } - return (null, null); + updatedPredicate = predicate; + return null; } - private (SqlExpression outer, SqlExpression inner) ValidateKeyComparison(SelectExpression inner, SqlBinaryExpression sqlBinaryExpression) + private SqlBinaryExpression ValidateKeyComparison(SelectExpression inner, SqlBinaryExpression sqlBinaryExpression) { if (sqlBinaryExpression.OperatorType == ExpressionType.Equal) { if (sqlBinaryExpression.Left is ColumnExpression leftColumn && sqlBinaryExpression.Right is ColumnExpression rightColumn) { - if (ContainsTableReference(this, leftColumn.Table) - && ContainsTableReference(inner, rightColumn.Table)) + if (ContainsTableReference(leftColumn.Table) + && inner.ContainsTableReference(rightColumn.Table)) { - return (leftColumn, rightColumn); + return sqlBinaryExpression; } - if (ContainsTableReference(this, rightColumn.Table) - && ContainsTableReference(inner, leftColumn.Table)) + if (ContainsTableReference(rightColumn.Table) + && inner.ContainsTableReference(leftColumn.Table)) { - return (rightColumn, leftColumn); + return sqlBinaryExpression.Update( + sqlBinaryExpression.Right, + sqlBinaryExpression.Left); } } } - return (null, null); + return null; } - private static bool ContainsTableReference(SelectExpression selectExpression, TableExpressionBase table) + private bool ContainsTableReference(TableExpressionBase table) { - return selectExpression.Tables.Any(te => ReferenceEquals(te is JoinExpressionBase jeb ? jeb.Table : te, table)); + return _tables.Any(te => ReferenceEquals(te is JoinExpressionBase jeb ? jeb.Table : te, table)); } public void AddInnerJoin(SelectExpression innerSelectExpression, SqlExpression joinPredicate, Type transparentIdentifierType) @@ -980,6 +997,7 @@ public SqlRemappingVisitor(IDictionary mappings } public SqlExpression Remap(SqlExpression sqlExpression) => (SqlExpression)Visit(sqlExpression); + public SelectExpression Remap(SelectExpression sqlExpression) => (SelectExpression)Visit(sqlExpression); public override Expression Visit(Expression expression) { diff --git a/src/EFCore/Query/Pipeline/ShapedQueryExpressionVisitor.cs b/src/EFCore/Query/Pipeline/ShapedQueryExpressionVisitor.cs index 6cb257adbd2..63a2af98cfe 100644 --- a/src/EFCore/Query/Pipeline/ShapedQueryExpressionVisitor.cs +++ b/src/EFCore/Query/Pipeline/ShapedQueryExpressionVisitor.cs @@ -166,9 +166,6 @@ private static readonly MethodInfo _startTrackingMethodInfo private readonly IEntityMaterializerSource _entityMaterializerSource; private readonly bool _trackQueryResults; - - private readonly List _variables = new List(); - private readonly List _expressions = new List(); private int _currentEntityIndex; public EntityMaterializerInjectingExpressionVisitor( @@ -180,9 +177,7 @@ public EntityMaterializerInjectingExpressionVisitor( public Expression Inject(Expression expression) { - _expressions.Add(Visit(expression)); - - return Expression.Block(_variables, _expressions); + return Visit(expression); } protected override Expression VisitExtension(Expression extensionExpression) diff --git a/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs index 0d87ff2875f..6578e9160a7 100644 --- a/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs @@ -45,7 +45,7 @@ public virtual Task Entity_equality_empty(bool isAsync) gs => gs.Where(g => g == new Gear())); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_multiple_one_to_one_and_one_to_many(bool isAsync) { @@ -82,7 +82,7 @@ public virtual Task ToString_guid_property_projection(bool isAsync) }); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory(Skip = "Issue#16225")] [MemberData(nameof(IsAsyncData))] public virtual Task Include_multiple_one_to_one_and_one_to_many_self_reference(bool isAsync) { @@ -99,7 +99,7 @@ public virtual Task Include_multiple_one_to_one_and_one_to_many_self_reference(b expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_multiple_one_to_one_optional_and_one_to_one_required(bool isAsync) { @@ -116,7 +116,7 @@ public virtual Task Include_multiple_one_to_one_optional_and_one_to_one_required expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory(Skip = "Issue#16225")] [MemberData(nameof(IsAsyncData))] public virtual Task Include_multiple_one_to_one_and_one_to_one_and_one_to_many(bool isAsync) { @@ -134,7 +134,7 @@ public virtual Task Include_multiple_one_to_one_and_one_to_one_and_one_to_many(b expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_multiple_circular(bool isAsync) { @@ -151,7 +151,7 @@ public virtual Task Include_multiple_circular(bool isAsync) expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_multiple_circular_with_filter(bool isAsync) { @@ -168,7 +168,7 @@ public virtual Task Include_multiple_circular_with_filter(bool isAsync) expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_using_alternate_key(bool isAsync) { @@ -184,7 +184,7 @@ public virtual Task Include_using_alternate_key(bool isAsync) expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory(Skip = "Issue#16225")] [MemberData(nameof(IsAsyncData))] public virtual Task Include_multiple_include_then_include(bool isAsync) { @@ -219,7 +219,7 @@ public virtual Task Include_multiple_include_then_include(bool isAsync) assertOrder: true); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_navigation_on_derived_type(bool isAsync) { @@ -234,7 +234,7 @@ public virtual Task Include_navigation_on_derived_type(bool isAsync) expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task String_based_Include_navigation_on_derived_type(bool isAsync) { @@ -249,7 +249,7 @@ public virtual Task String_based_Include_navigation_on_derived_type(bool isAsync expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Select_Where_Navigation_Included(bool isAsync) { @@ -269,7 +269,7 @@ where Maybe(t.Gear, () => t.Gear.Nickname) == "Marcus" expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_with_join_reference1(bool isAsync) { @@ -298,7 +298,7 @@ public virtual Task Include_with_join_reference1(bool isAsync) expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_with_join_reference2(bool isAsync) { @@ -327,7 +327,7 @@ public virtual Task Include_with_join_reference2(bool isAsync) expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_with_join_collection1(bool isAsync) { @@ -356,7 +356,7 @@ public virtual Task Include_with_join_collection1(bool isAsync) expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_with_join_collection2(bool isAsync) { @@ -385,7 +385,7 @@ public virtual Task Include_with_join_collection2(bool isAsync) expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual void Include_where_list_contains_navigation(bool isAsync) { @@ -406,7 +406,7 @@ public virtual void Include_where_list_contains_navigation(bool isAsync) } } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual void Include_where_list_contains_navigation2(bool isAsync) { @@ -447,7 +447,7 @@ public virtual void Navigation_accessed_twice_outside_and_inside_subquery(bool i } } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_with_join_multi_level(bool isAsync) { @@ -477,7 +477,7 @@ public virtual Task Include_with_join_multi_level(bool isAsync) expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_with_join_and_inheritance1(bool isAsync) { @@ -534,7 +534,7 @@ public virtual Task Include_with_join_and_inheritance_with_orderby_before_and_af expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_with_join_and_inheritance2(bool isAsync) { @@ -562,7 +562,7 @@ public virtual Task Include_with_join_and_inheritance2(bool isAsync) expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_with_join_and_inheritance3(bool isAsync) { @@ -590,7 +590,7 @@ public virtual Task Include_with_join_and_inheritance3(bool isAsync) expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_with_nested_navigation_in_order_by(bool isAsync) { @@ -2005,7 +2005,7 @@ join w in ws.OrderBy(ww => ww.Name) on g.FullName equals w.OwnerFullName elementSorter: w => w.Name); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Collection_with_inheritance_and_join_include_joined(bool isAsync) { @@ -2030,7 +2030,7 @@ public virtual Task Collection_with_inheritance_and_join_include_joined(bool isA }); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Collection_with_inheritance_and_join_include_source(bool isAsync) { @@ -2156,7 +2156,7 @@ public virtual void Non_unicode_string_literals_is_used_for_non_unicode_column_w } } - [ConditionalFact(Skip = "Issue #15611")] + [ConditionalFact(Skip = "Issue#16229")] public virtual void Include_on_GroupJoin_SelectMany_DefaultIfEmpty_with_coalesce_result1() { using (var context = CreateContext()) @@ -2179,7 +2179,7 @@ from g2 in grouping.DefaultIfEmpty() } } - [ConditionalFact(Skip = "Issue #15611")] + [ConditionalFact(Skip = "Issue#16229")] public virtual void Include_on_GroupJoin_SelectMany_DefaultIfEmpty_with_coalesce_result2() { using (var context = CreateContext()) @@ -2202,7 +2202,7 @@ from g2 in grouping.DefaultIfEmpty() } } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory(Skip = "Issue#16229")] [InlineData(false)] //[InlineData(true)] issue #12449 public virtual Task Include_on_GroupJoin_SelectMany_DefaultIfEmpty_with_coalesce_result3(bool isAsync) @@ -2223,7 +2223,7 @@ from g2 in grouping.DefaultIfEmpty() expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory(Skip = "Issue#16229")] [MemberData(nameof(IsAsyncData))] public virtual Task Include_on_GroupJoin_SelectMany_DefaultIfEmpty_with_coalesce_result4(bool isAsync) { @@ -2255,7 +2255,7 @@ from g2 in grouping.DefaultIfEmpty() }); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory(Skip = "Issue#16229")] [InlineData(false)] //[InlineData(true)] issue #12449 public virtual Task Include_on_GroupJoin_SelectMany_DefaultIfEmpty_with_inheritance_and_coalesce_result(bool isAsync) @@ -2276,7 +2276,7 @@ from g2 in grouping.DefaultIfEmpty() expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory(Skip = "Issue#16229")] [InlineData(false)] //[InlineData(true)] issue #12448 public virtual Task Include_on_GroupJoin_SelectMany_DefaultIfEmpty_with_conditional_result(bool isAsync) @@ -3054,7 +3054,7 @@ from g in grouping.DefaultIfEmpty() select s); } - [ConditionalTheory(Skip = "QueryIssue")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Any_with_optional_navigation_as_subquery_predicate_is_translated_to_sql(bool isAsync) { @@ -3197,7 +3197,7 @@ public virtual void Order_by_is_properly_lifted_from_subquery_with_same_order_by } } - [ConditionalFact(Skip = "Issue #15611")] + [ConditionalFact] public virtual void Where_is_properly_lifted_from_subquery_created_by_include() { using (var ctx = CreateContext()) @@ -3310,7 +3310,7 @@ join tag in ts on gear.Nickname equals tag.GearNickName assertOrder: true); } - [ConditionalFact(Skip = "Issue #15611")] + [ConditionalFact] public virtual void Subquery_created_by_include_gets_lifted_nested() { using (var ctx = CreateContext()) @@ -3513,7 +3513,7 @@ private static IEnumerable Veterans(IEnumerable gears) return gears.Where(g => g.Nickname == "Marcus" || g.Nickname == "Dom" || g.Nickname == "Cole Train" || g.Nickname == "Baird"); } - [ConditionalFact(Skip = "Issue#16089")] + [ConditionalFact] public virtual void Member_access_on_derived_entity_using_cast() { using (var ctx = CreateContext()) @@ -3537,7 +3537,7 @@ where f is LocustHorde } } - [ConditionalFact(Skip = "Issue#16089")] + [ConditionalFact] public virtual void Member_access_on_derived_materialized_entity_using_cast() { using (var ctx = CreateContext()) @@ -3561,7 +3561,7 @@ orderby f.Name } } - [ConditionalFact(Skip = "Issue#16089")] + [ConditionalFact] public virtual void Member_access_on_derived_entity_using_cast_and_let() { using (var ctx = CreateContext()) @@ -3586,7 +3586,7 @@ orderby horde.Name } } - [ConditionalFact(Skip = "Issue#16089")] + [ConditionalFact] public virtual void Property_access_on_derived_entity_using_cast() { using (var ctx = CreateContext()) @@ -3689,7 +3689,7 @@ on c1[City.NationPropertyName] equals c2[City.NationPropertyName] select new { c1.Name, c2.Location })); } - [ConditionalFact(Skip = "Issue#16089")] + [ConditionalFact] public virtual void Navigation_access_on_derived_entity_using_cast() { using (var ctx = CreateContext()) @@ -3713,7 +3713,7 @@ orderby f.Name } } - [ConditionalFact(Skip = "Issue#16089")] + [ConditionalFact] public virtual void Navigation_access_on_derived_materialized_entity_using_cast() { using (var ctx = CreateContext()) @@ -3740,7 +3740,7 @@ orderby f.Name } } - [ConditionalFact(Skip = "issue #16089")] + [ConditionalFact] public virtual void Navigation_access_via_EFProperty_on_derived_entity_using_cast() { using (var ctx = CreateContext()) @@ -3764,7 +3764,7 @@ orderby f.Name } } - [ConditionalFact(Skip = "issue #16089")] + [ConditionalFact] public virtual void Navigation_access_fk_on_derived_entity_using_cast() { using (var ctx = CreateContext()) @@ -3842,7 +3842,7 @@ orderby l.Name } } - [ConditionalFact(Skip = "Issue #15611")] + [ConditionalFact] public virtual void Include_on_derived_entity_using_OfType() { using (var ctx = CreateContext()) @@ -3861,7 +3861,7 @@ orderby lh.Name } } - [ConditionalFact(Skip = "Issue #15611")] + [ConditionalFact(Skip = "Issue#16089")] public virtual void Include_on_derived_entity_using_subquery_with_cast() { using (var ctx = CreateContext()) @@ -3882,7 +3882,7 @@ orderby lh.Name } } - [ConditionalFact(Skip = "Issue #15611")] + [ConditionalFact(Skip = "Issue#16089")] public virtual void Include_on_derived_entity_using_subquery_with_cast_AsNoTracking() { using (var ctx = CreateContext()) @@ -3903,7 +3903,7 @@ orderby lh.Name } } - [ConditionalFact(Skip = "Issue #15611")] + [ConditionalFact(Skip = "Issue#16089")] public virtual void Include_on_derived_entity_using_subquery_with_cast_cross_product_base_entity() { using (var ctx = CreateContext()) @@ -4051,7 +4051,7 @@ public virtual void Optional_navigation_with_collection_composite_key() } } - [ConditionalFact(Skip = "issue #16089")] + [ConditionalFact] public virtual void Select_null_conditional_with_inheritance() { using (var context = CreateContext()) @@ -4067,7 +4067,7 @@ public virtual void Select_null_conditional_with_inheritance() } } - [ConditionalFact(Skip = "Issue#16089")] + [ConditionalFact] public virtual void Select_null_conditional_with_inheritance_negative() { using (var context = CreateContext()) @@ -4144,7 +4144,7 @@ public virtual void Project_collection_navigation_with_inheritance3() } } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_reference_on_derived_type_using_string(bool isAsync) { @@ -4157,7 +4157,7 @@ public virtual Task Include_reference_on_derived_type_using_string(bool isAsync) }); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_reference_on_derived_type_using_string_nested1(bool isAsync) { @@ -4173,7 +4173,7 @@ public virtual Task Include_reference_on_derived_type_using_string_nested1(bool expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_reference_on_derived_type_using_string_nested2(bool isAsync) { @@ -4190,7 +4190,7 @@ public virtual Task Include_reference_on_derived_type_using_string_nested2(bool expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_reference_on_derived_type_using_lambda(bool isAsync) { @@ -4203,7 +4203,7 @@ public virtual Task Include_reference_on_derived_type_using_lambda(bool isAsync) }); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_reference_on_derived_type_using_lambda_with_soft_cast(bool isAsync) { @@ -4216,7 +4216,7 @@ public virtual Task Include_reference_on_derived_type_using_lambda_with_soft_cas }); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_reference_on_derived_type_using_lambda_with_tracking(bool isAsync) { @@ -4243,7 +4243,7 @@ public virtual Task Include_collection_on_derived_type_using_string(bool isAsync }); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_collection_on_derived_type_using_lambda(bool isAsync) { @@ -4256,7 +4256,7 @@ public virtual Task Include_collection_on_derived_type_using_lambda(bool isAsync }); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_collection_on_derived_type_using_lambda_with_soft_cast(bool isAsync) { @@ -4269,7 +4269,7 @@ public virtual Task Include_collection_on_derived_type_using_lambda_with_soft_ca }); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_base_navigation_on_derived_entity(bool isAsync) { @@ -4285,7 +4285,7 @@ public virtual Task Include_base_navigation_on_derived_entity(bool isAsync) expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task ThenInclude_collection_on_derived_after_base_reference(bool isAsync) { @@ -4301,7 +4301,7 @@ public virtual Task ThenInclude_collection_on_derived_after_base_reference(bool expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task ThenInclude_collection_on_derived_after_derived_reference(bool isAsync) { @@ -4318,7 +4318,7 @@ public virtual Task ThenInclude_collection_on_derived_after_derived_reference(bo expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task ThenInclude_collection_on_derived_after_derived_collection(bool isAsync) { @@ -4334,7 +4334,7 @@ public virtual Task ThenInclude_collection_on_derived_after_derived_collection(b expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task ThenInclude_reference_on_derived_after_derived_collection(bool isAsync) { @@ -4350,7 +4350,7 @@ public virtual Task ThenInclude_reference_on_derived_after_derived_collection(bo expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Multiple_derived_included_on_one_method(bool isAsync) { @@ -4367,7 +4367,7 @@ public virtual Task Multiple_derived_included_on_one_method(bool isAsync) expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_on_derived_multi_level(bool isAsync) { @@ -4384,7 +4384,7 @@ public virtual Task Include_on_derived_multi_level(bool isAsync) expectedIncludes); } - [ConditionalFact(Skip = "Issue #15611")] + [ConditionalFact(Skip = "Issue#15312")] public virtual void Include_collection_and_invalid_navigation_using_string_throws() { Assert.Equal( @@ -5817,7 +5817,7 @@ public virtual void Include_collection_group_by_reference() } } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_on_derived_type_with_order_by_and_paging(bool isAsync) { @@ -5836,7 +5836,7 @@ public virtual Task Include_on_derived_type_with_order_by_and_paging(bool isAsyn elementSorter: e => e.Name); } - [ConditionalTheory(Skip = "issue #16089")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Select_required_navigation_on_derived_type(bool isAsync) { @@ -5856,7 +5856,7 @@ public virtual Task Select_required_navigation_on_the_same_type_with_cast(bool i gs => gs.Select(g => g.CityOfBirth.Name)); } - [ConditionalTheory(Skip = "issue #16089")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Where_required_navigation_on_derived_type(bool isAsync) { @@ -6433,7 +6433,7 @@ public virtual Task Select_subquery_projecting_multiple_constants_inside_anonymo })); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_with_order_by_constant(bool isAsync) { @@ -6592,7 +6592,7 @@ public virtual void GroupBy_composite_key_with_Include() } } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_collection_OrderBy_aggregate(bool isAsync) { @@ -6608,7 +6608,7 @@ public virtual Task Include_collection_OrderBy_aggregate(bool isAsync) assertOrder: true); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_collection_with_complex_OrderBy2(bool isAsync) { @@ -7068,7 +7068,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 #15611")] + [ConditionalTheory(Skip = "Issue #15711")] [MemberData(nameof(IsAsyncData))] public virtual Task GroupBy_Property_Include_Aggregate_with_anonymous_selector(bool isAsync) { @@ -7172,7 +7172,7 @@ public virtual Task Include_with_group_by_and_FirstOrDefault_gets_properly_appli expectedIncludes); } - [ConditionalTheory(Skip = "Issue #15611")] + [ConditionalTheory] [MemberData(nameof(IsAsyncData))] public virtual Task Include_collection_with_Cast_to_base(bool isAsync) { @@ -7182,7 +7182,7 @@ public virtual Task Include_collection_with_Cast_to_base(bool isAsync) new List { new ExpectedInclude(e => e.Weapons, "Weapons") }); } - [ConditionalFact(Skip = "Issue #15611")] + [ConditionalFact(Skip = "Issue#16231")] public virtual Task Multiple_includes_with_client_method_around_qsre_and_also_projecting_included_collection() { using (var ctx = CreateContext()) @@ -7436,7 +7436,7 @@ public virtual void Nav_rewrite_Distinct_with_convert_anonymous() } } - [ConditionalFact(Skip = "Issue#16089")] + [ConditionalFact] public virtual void Nav_rewrite_with_convert1() { using (var ctx = CreateContext()) @@ -7446,7 +7446,7 @@ public virtual void Nav_rewrite_with_convert1() } } - [ConditionalFact(Skip = "Issue#16089")] + [ConditionalFact] public virtual void Nav_rewrite_with_convert2() { using (var ctx = CreateContext()) @@ -7456,7 +7456,7 @@ public virtual void Nav_rewrite_with_convert2() } } - [ConditionalFact(Skip = "Issue#16089")] + [ConditionalFact] public virtual void Nav_rewrite_with_convert3() { using (var ctx = CreateContext()) diff --git a/test/EFCore.Specification.Tests/Query/IncludeAsyncTestBase.cs b/test/EFCore.Specification.Tests/Query/IncludeAsyncTestBase.cs index c9f1a69aba7..fdf03a5f9ed 100644 --- a/test/EFCore.Specification.Tests/Query/IncludeAsyncTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/IncludeAsyncTestBase.cs @@ -20,7 +20,7 @@ public abstract class IncludeAsyncTestBase : IClassFixture protected TFixture Fixture { get; } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_collection() { using (var context = CreateContext()) @@ -37,7 +37,7 @@ var customers } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_collection_order_by_subquery() { using (var context = CreateContext()) @@ -55,7 +55,7 @@ var customer } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_closes_reader() { using (var context = CreateContext()) @@ -68,7 +68,7 @@ public virtual async Task Include_closes_reader() } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_collection_alias_generation() { using (var context = CreateContext()) @@ -82,7 +82,7 @@ var orders } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_collection_and_reference() { using (var context = CreateContext()) @@ -97,7 +97,7 @@ var orders } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_collection_as_no_tracking() { using (var context = CreateContext()) @@ -115,7 +115,7 @@ var customers } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_collection_as_no_tracking2() { using (var context = CreateContext()) @@ -135,7 +135,7 @@ var customers } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_collection_dependent_already_tracked() { using (var context = CreateContext()) @@ -159,7 +159,7 @@ var customer } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_collection_dependent_already_tracked_as_no_tracking() { using (var context = CreateContext()) @@ -184,7 +184,7 @@ var customer } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_collection_on_additional_from_clause() { using (var context = CreateContext()) @@ -202,7 +202,7 @@ from c2 in context.Set().Include(c => c.Orders) } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_collection_on_additional_from_clause_no_tracking() { using (var context = CreateContext()) @@ -220,7 +220,7 @@ from c2 in context.Set().AsNoTracking().Include(c => c.Orders) } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_collection_on_additional_from_clause_with_filter() { using (var context = CreateContext()) @@ -240,7 +240,7 @@ from c2 in context.Set() } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_collection_on_additional_from_clause2() { using (var context = CreateContext()) @@ -257,7 +257,7 @@ from c2 in context.Set().Include(c => c.Orders) } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_collection_on_join_clause_with_filter() { using (var context = CreateContext()) @@ -276,7 +276,7 @@ join o in context.Set() on c.CustomerID equals o.CustomerID } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_collection_on_join_clause_with_order_by_and_filter() { using (var context = CreateContext()) @@ -319,7 +319,7 @@ join o in context.Set() on c.CustomerID equals o.CustomerID into g } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact(Skip = "issue #15711")] public virtual async Task Include_collection_on_inner_group_join_clause_with_filter() { using (var context = CreateContext()) @@ -360,7 +360,7 @@ var customers } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_collection_order_by_key() { using (var context = CreateContext()) @@ -378,7 +378,7 @@ var customers } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_collection_order_by_non_key() { using (var context = CreateContext()) @@ -396,7 +396,7 @@ var customers } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_collection_principal_already_tracked() { using (var context = CreateContext()) @@ -419,7 +419,7 @@ var customer2 } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_collection_principal_already_tracked_as_no_tracking() { using (var context = CreateContext()) @@ -443,7 +443,7 @@ var customer2 } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_collection_single_or_default_no_result() { using (var context = CreateContext()) @@ -457,7 +457,7 @@ var customer } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_collection_when_projection() { using (var context = CreateContext()) @@ -473,7 +473,7 @@ var productIds } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_collection_with_filter() { using (var context = CreateContext()) @@ -491,7 +491,7 @@ var customers } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_collection_with_filter_reordered() { using (var context = CreateContext()) @@ -509,7 +509,7 @@ var customers } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_duplicate_collection() { using (var context = CreateContext()) @@ -540,7 +540,7 @@ from c2 in context.Set() } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_duplicate_collection_result_operator() { using (var context = CreateContext()) @@ -572,7 +572,7 @@ from c2 in context.Set() } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_duplicate_collection_result_operator2() { using (var context = CreateContext()) @@ -693,7 +693,7 @@ from o2 in context.Set() } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_multi_level_reference_and_collection_predicate() { using (var context = CreateContext()) @@ -728,7 +728,7 @@ var customers } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_multi_level_collection_and_then_include_reference_predicate() { using (var context = CreateContext()) @@ -763,7 +763,7 @@ var orderDetails } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_multiple_references_and_collection_multi_level() { using (var context = CreateContext()) @@ -780,7 +780,7 @@ var orderDetails } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_multiple_references_and_collection_multi_level_reverse() { using (var context = CreateContext()) @@ -860,7 +860,7 @@ var orders } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_reference_and_collection() { using (var context = CreateContext()) @@ -981,7 +981,7 @@ var orders } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_references_and_collection_multi_level() { using (var context = CreateContext()) @@ -997,7 +997,7 @@ var orderDetails } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_collection_then_include_collection() { using (var context = CreateContext()) @@ -1013,7 +1013,7 @@ var customers } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_collection_then_include_collection_then_include_reference() { using (var context = CreateContext()) @@ -1029,7 +1029,7 @@ var customers } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_collection_then_include_collection_predicate() { using (var context = CreateContext()) @@ -1045,7 +1045,7 @@ var customer } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_references_and_collection_multi_level_predicate() { using (var context = CreateContext()) @@ -1077,7 +1077,7 @@ var orderDetails } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_multi_level_reference_then_include_collection_predicate() { using (var context = CreateContext()) @@ -1092,7 +1092,7 @@ var order } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_multiple_references_then_include_collection_multi_level() { using (var context = CreateContext()) @@ -1109,7 +1109,7 @@ var orderDetails } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_multiple_references_then_include_collection_multi_level_reverse() { using (var context = CreateContext()) @@ -1158,7 +1158,7 @@ var orderDetails } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_references_then_include_collection_multi_level() { using (var context = CreateContext()) @@ -1174,7 +1174,7 @@ var orderDetails } } - [ConditionalFact(Skip = "issue #15064")] + [ConditionalFact] public virtual async Task Include_references_then_include_collection_multi_level_predicate() { using (var context = CreateContext()) diff --git a/test/EFCore.Specification.Tests/Query/IncludeTestBase.cs b/test/EFCore.Specification.Tests/Query/IncludeTestBase.cs index 576efba30fc..4fea65ad523 100644 --- a/test/EFCore.Specification.Tests/Query/IncludeTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/IncludeTestBase.cs @@ -1570,7 +1570,7 @@ var customers } } - [ConditionalTheory(Skip = "Issue#15871")] + [ConditionalTheory] [InlineData(false)] [InlineData(true)] public virtual void Include_duplicate_collection(bool useString) @@ -1639,7 +1639,7 @@ from c2 in context.Set() } } - [ConditionalTheory(Skip = "Issue#15871")] + [ConditionalTheory] [InlineData(false)] [InlineData(true)] public virtual void Include_duplicate_collection_result_operator(bool useString) @@ -2122,7 +2122,7 @@ var orderDetails } } - [ConditionalTheory(Skip = "Issue#15871")] + [ConditionalTheory] [InlineData(false)] [InlineData(true)] public virtual void Include_multiple_references_and_collection_multi_level(bool useString) @@ -2849,7 +2849,7 @@ var order } } - [ConditionalTheory(Skip = "Issue#15871")] + [ConditionalTheory] [InlineData(false)] [InlineData(true)] public virtual void Include_multiple_references_then_include_collection_multi_level(bool useString) diff --git a/test/EFCore.Specification.Tests/Query/InheritanceTestBase.cs b/test/EFCore.Specification.Tests/Query/InheritanceTestBase.cs index a7e71c48166..45cc674cba3 100644 --- a/test/EFCore.Specification.Tests/Query/InheritanceTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/InheritanceTestBase.cs @@ -392,7 +392,7 @@ var birds } } - [ConditionalFact(Skip = "Issue#14935")] + [ConditionalFact] public virtual void Discriminator_with_cast_in_shadow_property() { using (var context = CreateContext()) diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/AsyncSimpleQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/AsyncSimpleQuerySqlServerTest.cs index 4d03bee11e9..848c8a4f2eb 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/AsyncSimpleQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/AsyncSimpleQuerySqlServerTest.cs @@ -63,7 +63,7 @@ orderby o2.OrderID return Task.WhenAll(tasks); } - [ConditionalFact] + [ConditionalFact(Skip = "Issue#16218")] public Task Race_when_context_disposed_before_query_termination() { DbSet task; @@ -185,5 +185,17 @@ await context.Database.ExecuteSqlRawAsync( } } } + + [ConditionalFact(Skip = "Issue#16218")] + public override Task Select_bitwise_and_with_logical_and() + { + return base.Select_bitwise_and_with_logical_and(); + } + + [ConditionalFact(Skip = "Issue#16218")] + public override Task Mixed_sync_async_in_query_cache() + { + return base.Mixed_sync_async_in_query_cache(); + } } } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs index 0491e125fa3..39304510bc1 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs @@ -35,27 +35,15 @@ public override async Task Include_multiple_one_to_one_and_one_to_many(bool isAs await base.Include_multiple_one_to_one_and_one_to_many(isAsync); AssertSql( - @"SELECT [t].[Id], [t].[GearNickName], [t].[GearSquadId], [t].[Note], [t0].[Nickname], [t0].[SquadId], [t0].[AssignedCityName], [t0].[CityOrBirthName], [t0].[Discriminator], [t0].[FullName], [t0].[HasSoulPatch], [t0].[LeaderNickname], [t0].[LeaderSquadId], [t0].[Rank] + @"SELECT [t].[Id], [t].[GearNickName], [t].[GearSquadId], [t].[Note], [t0].[Nickname], [t0].[SquadId], [t0].[AssignedCityName], [t0].[CityOrBirthName], [t0].[Discriminator], [t0].[FullName], [t0].[HasSoulPatch], [t0].[LeaderNickname], [t0].[LeaderSquadId], [t0].[Rank], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] FROM [Tags] AS [t] LEFT JOIN ( - SELECT [t.Gear].* - FROM [Gears] AS [t.Gear] - WHERE [t.Gear].[Discriminator] IN (N'Officer', N'Gear') -) AS [t0] ON ([t].[GearNickName] = [t0].[Nickname]) AND ([t].[GearSquadId] = [t0].[SquadId]) -ORDER BY [t0].[FullName]", - // - @"SELECT [t.Gear.Weapons].[Id], [t.Gear.Weapons].[AmmunitionType], [t.Gear.Weapons].[IsAutomatic], [t.Gear.Weapons].[Name], [t.Gear.Weapons].[OwnerFullName], [t.Gear.Weapons].[SynergyWithId] -FROM [Weapons] AS [t.Gear.Weapons] -INNER JOIN ( - SELECT DISTINCT [t2].[FullName] - FROM [Tags] AS [t1] - LEFT JOIN ( - SELECT [t.Gear0].* - FROM [Gears] AS [t.Gear0] - WHERE [t.Gear0].[Discriminator] IN (N'Officer', N'Gear') - ) AS [t2] ON ([t1].[GearNickName] = [t2].[Nickname]) AND ([t1].[GearSquadId] = [t2].[SquadId]) -) AS [t3] ON [t.Gear.Weapons].[OwnerFullName] = [t3].[FullName] -ORDER BY [t3].[FullName]"); + 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 [t0] ON (([t].[GearNickName] = [t0].[Nickname]) AND [t].[GearNickName] IS NOT NULL) AND (([t].[GearSquadId] = [t0].[SquadId]) AND [t].[GearSquadId] IS NOT NULL) +LEFT JOIN [Weapons] AS [w] ON [t0].[FullName] = [w].[OwnerFullName] +ORDER BY [t].[Id]"); } public override async Task Include_multiple_one_to_one_and_one_to_many_self_reference(bool isAsync) @@ -122,14 +110,14 @@ public override async Task Include_multiple_one_to_one_optional_and_one_to_one_r await base.Include_multiple_one_to_one_optional_and_one_to_one_required(isAsync); AssertSql( - @"SELECT [t].[Id], [t].[GearNickName], [t].[GearSquadId], [t].[Note], [t0].[Nickname], [t0].[SquadId], [t0].[AssignedCityName], [t0].[CityOrBirthName], [t0].[Discriminator], [t0].[FullName], [t0].[HasSoulPatch], [t0].[LeaderNickname], [t0].[LeaderSquadId], [t0].[Rank], [t.Gear.Squad].[Id], [t.Gear.Squad].[InternalNumber], [t.Gear.Squad].[Name] + @"SELECT [t].[Id], [t].[GearNickName], [t].[GearSquadId], [t].[Note], [t0].[Nickname], [t0].[SquadId], [t0].[AssignedCityName], [t0].[CityOrBirthName], [t0].[Discriminator], [t0].[FullName], [t0].[HasSoulPatch], [t0].[LeaderNickname], [t0].[LeaderSquadId], [t0].[Rank], [s].[Id], [s].[InternalNumber], [s].[Name] FROM [Tags] AS [t] LEFT JOIN ( - SELECT [t.Gear].* - FROM [Gears] AS [t.Gear] - WHERE [t.Gear].[Discriminator] IN (N'Officer', N'Gear') -) AS [t0] ON ([t].[GearNickName] = [t0].[Nickname]) AND ([t].[GearSquadId] = [t0].[SquadId]) -LEFT JOIN [Squads] AS [t.Gear.Squad] ON [t0].[SquadId] = [t.Gear.Squad].[Id]"); + 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 [t0] ON (([t].[GearNickName] = [t0].[Nickname]) AND [t].[GearNickName] IS NOT NULL) AND (([t].[GearSquadId] = [t0].[SquadId]) AND [t].[GearSquadId] IS NOT NULL) +LEFT JOIN [Squads] AS [s] ON [t0].[SquadId] = [s].[Id]"); } public override async Task Include_multiple_circular(bool isAsync) @@ -137,22 +125,16 @@ public override async Task Include_multiple_circular(bool isAsync) await base.Include_multiple_circular(isAsync); AssertSql( - @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [g.CityOfBirth].[Name], [g.CityOfBirth].[Location], [g.CityOfBirth].[Nation] + @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [c].[Name], [c].[Location], [c].[Nation], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank] FROM [Gears] AS [g] -INNER JOIN [Cities] AS [g.CityOfBirth] ON [g].[CityOrBirthName] = [g.CityOfBirth].[Name] -WHERE [g].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [g.CityOfBirth].[Name]", - // - @"SELECT [g.CityOfBirth.StationedGears].[Nickname], [g.CityOfBirth.StationedGears].[SquadId], [g.CityOfBirth.StationedGears].[AssignedCityName], [g.CityOfBirth.StationedGears].[CityOrBirthName], [g.CityOfBirth.StationedGears].[Discriminator], [g.CityOfBirth.StationedGears].[FullName], [g.CityOfBirth.StationedGears].[HasSoulPatch], [g.CityOfBirth.StationedGears].[LeaderNickname], [g.CityOfBirth.StationedGears].[LeaderSquadId], [g.CityOfBirth.StationedGears].[Rank] -FROM [Gears] AS [g.CityOfBirth.StationedGears] -INNER JOIN ( - SELECT DISTINCT [g.CityOfBirth0].[Name] +INNER JOIN [Cities] AS [c] ON [g].[CityOrBirthName] = [c].[Name] +LEFT 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] - INNER JOIN [Cities] AS [g.CityOfBirth0] ON [g0].[CityOrBirthName] = [g.CityOfBirth0].[Name] - WHERE [g0].[Discriminator] IN (N'Officer', N'Gear') -) AS [t] ON [g.CityOfBirth.StationedGears].[AssignedCityName] = [t].[Name] -WHERE [g.CityOfBirth.StationedGears].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [t].[Name]"); + WHERE [g0].[Discriminator] IN (N'Gear', N'Officer') +) AS [t] ON [c].[Name] = [t].[AssignedCityName] +WHERE [g].[Discriminator] IN (N'Gear', N'Officer') +ORDER BY [g].[Nickname], [g].[SquadId], [c].[Name]"); } public override async Task Include_multiple_circular_with_filter(bool isAsync) @@ -160,22 +142,16 @@ public override async Task Include_multiple_circular_with_filter(bool isAsync) await base.Include_multiple_circular_with_filter(isAsync); AssertSql( - @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [g.CityOfBirth].[Name], [g.CityOfBirth].[Location], [g.CityOfBirth].[Nation] + @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [c].[Name], [c].[Location], [c].[Nation], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank] FROM [Gears] AS [g] -INNER JOIN [Cities] AS [g.CityOfBirth] ON [g].[CityOrBirthName] = [g.CityOfBirth].[Name] -WHERE [g].[Discriminator] IN (N'Officer', N'Gear') AND ([g].[Nickname] = N'Marcus') -ORDER BY [g.CityOfBirth].[Name]", - // - @"SELECT [g.CityOfBirth.StationedGears].[Nickname], [g.CityOfBirth.StationedGears].[SquadId], [g.CityOfBirth.StationedGears].[AssignedCityName], [g.CityOfBirth.StationedGears].[CityOrBirthName], [g.CityOfBirth.StationedGears].[Discriminator], [g.CityOfBirth.StationedGears].[FullName], [g.CityOfBirth.StationedGears].[HasSoulPatch], [g.CityOfBirth.StationedGears].[LeaderNickname], [g.CityOfBirth.StationedGears].[LeaderSquadId], [g.CityOfBirth.StationedGears].[Rank] -FROM [Gears] AS [g.CityOfBirth.StationedGears] -INNER JOIN ( - SELECT DISTINCT [g.CityOfBirth0].[Name] +INNER JOIN [Cities] AS [c] ON [g].[CityOrBirthName] = [c].[Name] +LEFT 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] - INNER JOIN [Cities] AS [g.CityOfBirth0] ON [g0].[CityOrBirthName] = [g.CityOfBirth0].[Name] - WHERE [g0].[Discriminator] IN (N'Officer', N'Gear') AND ([g0].[Nickname] = N'Marcus') -) AS [t] ON [g.CityOfBirth.StationedGears].[AssignedCityName] = [t].[Name] -WHERE [g.CityOfBirth.StationedGears].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [t].[Name]"); + WHERE [g0].[Discriminator] IN (N'Gear', N'Officer') +) AS [t] ON [c].[Name] = [t].[AssignedCityName] +WHERE [g].[Discriminator] IN (N'Gear', N'Officer') AND ([g].[Nickname] = N'Marcus') +ORDER BY [g].[Nickname], [g].[SquadId], [c].[Name]"); } public override async Task Include_using_alternate_key(bool isAsync) @@ -183,19 +159,11 @@ public override async Task Include_using_alternate_key(bool isAsync) await base.Include_using_alternate_key(isAsync); AssertSql( - @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] + @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] FROM [Gears] AS [g] -WHERE [g].[Discriminator] IN (N'Officer', N'Gear') AND ([g].[Nickname] = N'Marcus') -ORDER BY [g].[FullName]", - // - @"SELECT [g.Weapons].[Id], [g.Weapons].[AmmunitionType], [g.Weapons].[IsAutomatic], [g.Weapons].[Name], [g.Weapons].[OwnerFullName], [g.Weapons].[SynergyWithId] -FROM [Weapons] AS [g.Weapons] -INNER JOIN ( - SELECT [g0].[FullName] - FROM [Gears] AS [g0] - WHERE [g0].[Discriminator] IN (N'Officer', N'Gear') AND ([g0].[Nickname] = N'Marcus') -) AS [t] ON [g.Weapons].[OwnerFullName] = [t].[FullName] -ORDER BY [t].[FullName]"); +LEFT JOIN [Weapons] AS [w] ON [g].[FullName] = [w].[OwnerFullName] +WHERE [g].[Discriminator] IN (N'Gear', N'Officer') AND ([g].[Nickname] = N'Marcus') +ORDER BY [g].[Nickname], [g].[SquadId]"); } public override async Task Include_multiple_include_then_include(bool isAsync) @@ -268,20 +236,15 @@ public override async Task Include_navigation_on_derived_type(bool isAsync) await base.Include_navigation_on_derived_type(isAsync); AssertSql( - @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] + @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank] FROM [Gears] AS [g] -WHERE [g].[Discriminator] = N'Officer' -ORDER BY [g].[Nickname], [g].[SquadId]", - // - @"SELECT [o.Reports].[Nickname], [o.Reports].[SquadId], [o.Reports].[AssignedCityName], [o.Reports].[CityOrBirthName], [o.Reports].[Discriminator], [o.Reports].[FullName], [o.Reports].[HasSoulPatch], [o.Reports].[LeaderNickname], [o.Reports].[LeaderSquadId], [o.Reports].[Rank] -FROM [Gears] AS [o.Reports] -INNER JOIN ( - SELECT [g0].[Nickname], [g0].[SquadId] +LEFT 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] = N'Officer' -) AS [t] ON ([o.Reports].[LeaderNickname] = [t].[Nickname]) AND ([o.Reports].[LeaderSquadId] = [t].[SquadId]) -WHERE [o.Reports].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [t].[Nickname], [t].[SquadId]"); + WHERE [g0].[Discriminator] IN (N'Gear', N'Officer') +) AS [t] ON (([g].[Nickname] = [t].[LeaderNickname]) AND [t].[LeaderNickname] IS NOT NULL) AND ([g].[SquadId] = [t].[LeaderSquadId]) +WHERE [g].[Discriminator] IN (N'Gear', N'Officer') AND ([g].[Discriminator] = N'Officer') +ORDER BY [g].[Nickname], [g].[SquadId]"); } public override async Task String_based_Include_navigation_on_derived_type(bool isAsync) @@ -289,20 +252,15 @@ public override async Task String_based_Include_navigation_on_derived_type(bool await base.String_based_Include_navigation_on_derived_type(isAsync); AssertSql( - @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] + @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank] FROM [Gears] AS [g] -WHERE [g].[Discriminator] = N'Officer' -ORDER BY [g].[Nickname], [g].[SquadId]", - // - @"SELECT [o.Reports].[Nickname], [o.Reports].[SquadId], [o.Reports].[AssignedCityName], [o.Reports].[CityOrBirthName], [o.Reports].[Discriminator], [o.Reports].[FullName], [o.Reports].[HasSoulPatch], [o.Reports].[LeaderNickname], [o.Reports].[LeaderSquadId], [o.Reports].[Rank] -FROM [Gears] AS [o.Reports] -INNER JOIN ( - SELECT [g0].[Nickname], [g0].[SquadId] +LEFT 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] = N'Officer' -) AS [t] ON ([o.Reports].[LeaderNickname] = [t].[Nickname]) AND ([o.Reports].[LeaderSquadId] = [t].[SquadId]) -WHERE [o.Reports].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [t].[Nickname], [t].[SquadId]"); + WHERE [g0].[Discriminator] IN (N'Gear', N'Officer') +) AS [t] ON (([g].[Nickname] = [t].[LeaderNickname]) AND [t].[LeaderNickname] IS NOT NULL) AND ([g].[SquadId] = [t].[LeaderSquadId]) +WHERE [g].[Discriminator] IN (N'Gear', N'Officer') AND ([g].[Discriminator] = N'Officer') +ORDER BY [g].[Nickname], [g].[SquadId]"); } public override async Task Select_Where_Navigation_Included(bool isAsync) @@ -310,14 +268,14 @@ public override async Task Select_Where_Navigation_Included(bool isAsync) await base.Select_Where_Navigation_Included(isAsync); AssertSql( - @"SELECT [o].[Id], [o].[GearNickName], [o].[GearSquadId], [o].[Note], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank] -FROM [Tags] AS [o] + @"SELECT [t].[Id], [t].[GearNickName], [t].[GearSquadId], [t].[Note], [t0].[Nickname], [t0].[SquadId], [t0].[AssignedCityName], [t0].[CityOrBirthName], [t0].[Discriminator], [t0].[FullName], [t0].[HasSoulPatch], [t0].[LeaderNickname], [t0].[LeaderSquadId], [t0].[Rank] +FROM [Tags] AS [t] LEFT JOIN ( - SELECT [o.Gear].* - FROM [Gears] AS [o.Gear] - WHERE [o.Gear].[Discriminator] IN (N'Officer', N'Gear') -) AS [t] ON ([o].[GearNickName] = [t].[Nickname]) AND ([o].[GearSquadId] = [t].[SquadId]) -WHERE [t].[Nickname] = N'Marcus'"); + 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 [t0] ON (([t].[GearNickName] = [t0].[Nickname]) AND [t].[GearNickName] IS NOT NULL) AND (([t].[GearSquadId] = [t0].[SquadId]) AND [t].[GearSquadId] IS NOT NULL) +WHERE ([t0].[Nickname] = N'Marcus') AND [t0].[Nickname] IS NOT NULL"); } public override async Task Include_with_join_reference1(bool isAsync) @@ -325,11 +283,11 @@ public override async Task Include_with_join_reference1(bool isAsync) await base.Include_with_join_reference1(isAsync); AssertSql( - @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [g.CityOfBirth].[Name], [g.CityOfBirth].[Location], [g.CityOfBirth].[Nation] + @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [c].[Name], [c].[Location], [c].[Nation] FROM [Gears] AS [g] -INNER JOIN [Cities] AS [g.CityOfBirth] ON [g].[CityOrBirthName] = [g.CityOfBirth].[Name] -INNER JOIN [Tags] AS [t] ON ([g].[SquadId] = [t].[GearSquadId]) AND ([g].[Nickname] = [t].[GearNickName]) -WHERE [g].[Discriminator] IN (N'Officer', N'Gear')"); +INNER JOIN [Tags] AS [t] ON (([g].[SquadId] = [t].[GearSquadId]) AND [t].[GearSquadId] IS NOT NULL) AND (([g].[Nickname] = [t].[GearNickName]) AND [t].[GearNickName] IS NOT NULL) +INNER JOIN [Cities] AS [c] ON [g].[CityOrBirthName] = [c].[Name] +WHERE [g].[Discriminator] IN (N'Gear', N'Officer')"); } public override async Task Include_with_join_reference2(bool isAsync) @@ -337,11 +295,14 @@ public override async Task Include_with_join_reference2(bool isAsync) await base.Include_with_join_reference2(isAsync); AssertSql( - @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [g.CityOfBirth].[Name], [g.CityOfBirth].[Location], [g.CityOfBirth].[Nation] -FROM [Tags] AS [t] -INNER JOIN [Gears] AS [g] ON ([t].[GearSquadId] = [g].[SquadId]) AND ([t].[GearNickName] = [g].[Nickname]) -INNER JOIN [Cities] AS [g.CityOfBirth] ON [g].[CityOrBirthName] = [g.CityOfBirth].[Name] -WHERE [g].[Discriminator] IN (N'Officer', N'Gear')"); + @"SELECT [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank], [c].[Name], [c].[Location], [c].[Nation] +FROM [Tags] AS [t0] +INNER JOIN ( + 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] ON (([t0].[GearSquadId] = [t].[SquadId]) AND [t0].[GearSquadId] IS NOT NULL) AND (([t0].[GearNickName] = [t].[Nickname]) AND [t0].[GearNickName] IS NOT NULL) +INNER JOIN [Cities] AS [c] ON [t].[CityOrBirthName] = [c].[Name]"); } public override async Task Include_with_join_collection1(bool isAsync) @@ -349,21 +310,12 @@ public override async Task Include_with_join_collection1(bool isAsync) await base.Include_with_join_collection1(isAsync); AssertSql( - @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] + @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [t].[Id], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] FROM [Gears] AS [g] -INNER JOIN [Tags] AS [t] ON ([g].[SquadId] = [t].[GearSquadId]) AND ([g].[Nickname] = [t].[GearNickName]) -WHERE [g].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [g].[FullName]", - // - @"SELECT [g.Weapons].[Id], [g.Weapons].[AmmunitionType], [g.Weapons].[IsAutomatic], [g.Weapons].[Name], [g.Weapons].[OwnerFullName], [g.Weapons].[SynergyWithId] -FROM [Weapons] AS [g.Weapons] -INNER JOIN ( - SELECT DISTINCT [g0].[FullName] - FROM [Gears] AS [g0] - INNER JOIN [Tags] AS [t0] ON ([g0].[SquadId] = [t0].[GearSquadId]) AND ([g0].[Nickname] = [t0].[GearNickName]) - WHERE [g0].[Discriminator] IN (N'Officer', N'Gear') -) AS [t1] ON [g.Weapons].[OwnerFullName] = [t1].[FullName] -ORDER BY [t1].[FullName]"); +INNER JOIN [Tags] AS [t] ON (([g].[SquadId] = [t].[GearSquadId]) AND [t].[GearSquadId] IS NOT NULL) AND (([g].[Nickname] = [t].[GearNickName]) AND [t].[GearNickName] IS NOT NULL) +LEFT JOIN [Weapons] AS [w] ON [g].[FullName] = [w].[OwnerFullName] +WHERE [g].[Discriminator] IN (N'Gear', N'Officer') +ORDER BY [g].[Nickname], [g].[SquadId], [t].[Id]"); } public override async Task Include_with_join_collection2(bool isAsync) @@ -371,21 +323,15 @@ public override async Task Include_with_join_collection2(bool isAsync) await base.Include_with_join_collection2(isAsync); AssertSql( - @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] -FROM [Tags] AS [t] -INNER JOIN [Gears] AS [g] ON ([t].[GearSquadId] = [g].[SquadId]) AND ([t].[GearNickName] = [g].[Nickname]) -WHERE [g].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [g].[FullName]", - // - @"SELECT [g.Weapons].[Id], [g.Weapons].[AmmunitionType], [g.Weapons].[IsAutomatic], [g.Weapons].[Name], [g.Weapons].[OwnerFullName], [g.Weapons].[SynergyWithId] -FROM [Weapons] AS [g.Weapons] + @"SELECT [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank], [t0].[Id], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] +FROM [Tags] AS [t0] INNER JOIN ( - SELECT DISTINCT [g0].[FullName] - FROM [Tags] AS [t0] - INNER JOIN [Gears] AS [g0] ON ([t0].[GearSquadId] = [g0].[SquadId]) AND ([t0].[GearNickName] = [g0].[Nickname]) - WHERE [g0].[Discriminator] IN (N'Officer', N'Gear') -) AS [t1] ON [g.Weapons].[OwnerFullName] = [t1].[FullName] -ORDER BY [t1].[FullName]"); + 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] ON (([t0].[GearSquadId] = [t].[SquadId]) AND [t0].[GearSquadId] IS NOT NULL) AND (([t0].[GearNickName] = [t].[Nickname]) AND [t0].[GearNickName] IS NOT NULL) +LEFT JOIN [Weapons] AS [w] ON [t].[FullName] = [w].[OwnerFullName] +ORDER BY [t0].[Id], [t].[Nickname], [t].[SquadId]"); } public override void Include_where_list_contains_navigation(bool isAsync) @@ -394,16 +340,12 @@ public override void Include_where_list_contains_navigation(bool isAsync) AssertSql( @"SELECT [t].[Id] -FROM [Tags] AS [t]"); - - Assert.Contains( - "SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [g.Tag].[Id], [g.Tag].[GearNickName], [g.Tag].[GearSquadId], [g.Tag].[Note]" - + _eol + - "FROM [Gears] AS [g]" + _eol + - "LEFT JOIN [Tags] AS [g.Tag] ON ([g].[Nickname] = [g.Tag].[GearNickName]) AND ([g].[SquadId] = [g.Tag].[GearSquadId])" - + _eol + - "WHERE [g].[Discriminator] IN (N'Officer', N'Gear') AND ([g.Tag].[Id] IS NOT NULL AND [g.Tag].[Id] IN (", - Fixture.TestSqlLoggerFactory.SqlStatements[1]); +FROM [Tags] AS [t]", + // + @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [t].[Id], [t].[GearNickName], [t].[GearSquadId], [t].[Note] +FROM [Gears] AS [g] +LEFT JOIN [Tags] AS [t] ON (([g].[Nickname] = [t].[GearNickName]) AND [t].[GearNickName] IS NOT NULL) AND (([g].[SquadId] = [t].[GearSquadId]) AND [t].[GearSquadId] IS NOT NULL) +WHERE [g].[Discriminator] IN (N'Gear', N'Officer') AND ([t].[Id] IS NOT NULL AND [t].[Id] IN ('34c8d86e-a4ac-4be5-827f-584dda348a07', 'df36f493-463f-4123-83f9-6b135deeb7ba', 'a8ad98f9-e023-4e2a-9a70-c2728455bd34', '70534e05-782c-4052-8720-c2c54481ce5f', 'a7be028a-0cf2-448f-ab55-ce8bc5d8cf69', 'b39a6fba-9026-4d69-828e-fd7068673e57'))"); } public override void Include_where_list_contains_navigation2(bool isAsync) @@ -412,35 +354,20 @@ public override void Include_where_list_contains_navigation2(bool isAsync) AssertSql( @"SELECT [t].[Id] -FROM [Tags] AS [t]"); - - Assert.Contains( - "SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [g.Tag].[Id], [g.Tag].[GearNickName], [g.Tag].[GearSquadId], [g.Tag].[Note]" - + _eol + - "FROM [Gears] AS [g]" + _eol + - "LEFT JOIN [Tags] AS [g.Tag] ON ([g].[Nickname] = [g.Tag].[GearNickName]) AND ([g].[SquadId] = [g.Tag].[GearSquadId])" - + _eol + - "INNER JOIN [Cities] AS [g.CityOfBirth] ON [g].[CityOrBirthName] = [g.CityOfBirth].[Name]" + _eol + - "WHERE [g].[Discriminator] IN (N'Officer', N'Gear') AND ([g.CityOfBirth].[Location] IS NOT NULL AND [g.Tag].[Id] IN (", - Fixture.TestSqlLoggerFactory.SqlStatements[1]); +FROM [Tags] AS [t]", + // + @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [t].[Id], [t].[GearNickName], [t].[GearSquadId], [t].[Note] +FROM [Gears] AS [g] +LEFT JOIN [Tags] AS [t] ON (([g].[Nickname] = [t].[GearNickName]) AND [t].[GearNickName] IS NOT NULL) AND (([g].[SquadId] = [t].[GearSquadId]) AND [t].[GearSquadId] IS NOT NULL) +INNER JOIN [Cities] AS [c] ON [g].[CityOrBirthName] = [c].[Name] +WHERE [g].[Discriminator] IN (N'Gear', N'Officer') AND ([c].[Location] IS NOT NULL AND [t].[Id] IN ('34c8d86e-a4ac-4be5-827f-584dda348a07', 'df36f493-463f-4123-83f9-6b135deeb7ba', 'a8ad98f9-e023-4e2a-9a70-c2728455bd34', '70534e05-782c-4052-8720-c2c54481ce5f', 'a7be028a-0cf2-448f-ab55-ce8bc5d8cf69', 'b39a6fba-9026-4d69-828e-fd7068673e57'))"); } public override void Navigation_accessed_twice_outside_and_inside_subquery(bool isAsync) { base.Navigation_accessed_twice_outside_and_inside_subquery(isAsync); - AssertSql( - @"SELECT [t].[Id] -FROM [Tags] AS [t]"); - - Assert.Contains( - "SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank]" - + _eol + - "FROM [Gears] AS [g]" + _eol + - "LEFT JOIN [Tags] AS [g.Tag] ON ([g].[Nickname] = [g.Tag].[GearNickName]) AND ([g].[SquadId] = [g.Tag].[GearSquadId])" - + _eol + - "WHERE [g].[Discriminator] IN (N'Officer', N'Gear') AND ([g.Tag].[Id] IS NOT NULL AND [g.Tag].[Id] IN (", - Fixture.TestSqlLoggerFactory.SqlStatements[1]); + AssertSql(" "); } public override async Task Include_with_join_multi_level(bool isAsync) @@ -448,24 +375,17 @@ public override async Task Include_with_join_multi_level(bool isAsync) await base.Include_with_join_multi_level(isAsync); AssertSql( - @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [g.CityOfBirth].[Name], [g.CityOfBirth].[Location], [g.CityOfBirth].[Nation] + @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [c].[Name], [c].[Location], [c].[Nation], [t].[Id], [t0].[Nickname], [t0].[SquadId], [t0].[AssignedCityName], [t0].[CityOrBirthName], [t0].[Discriminator], [t0].[FullName], [t0].[HasSoulPatch], [t0].[LeaderNickname], [t0].[LeaderSquadId], [t0].[Rank] FROM [Gears] AS [g] -INNER JOIN [Cities] AS [g.CityOfBirth] ON [g].[CityOrBirthName] = [g.CityOfBirth].[Name] -INNER JOIN [Tags] AS [t] ON ([g].[SquadId] = [t].[GearSquadId]) AND ([g].[Nickname] = [t].[GearNickName]) -WHERE [g].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [g.CityOfBirth].[Name]", - // - @"SELECT [g.CityOfBirth.StationedGears].[Nickname], [g.CityOfBirth.StationedGears].[SquadId], [g.CityOfBirth.StationedGears].[AssignedCityName], [g.CityOfBirth.StationedGears].[CityOrBirthName], [g.CityOfBirth.StationedGears].[Discriminator], [g.CityOfBirth.StationedGears].[FullName], [g.CityOfBirth.StationedGears].[HasSoulPatch], [g.CityOfBirth.StationedGears].[LeaderNickname], [g.CityOfBirth.StationedGears].[LeaderSquadId], [g.CityOfBirth.StationedGears].[Rank] -FROM [Gears] AS [g.CityOfBirth.StationedGears] -INNER JOIN ( - SELECT DISTINCT [g.CityOfBirth0].[Name] +INNER JOIN [Tags] AS [t] ON (([g].[SquadId] = [t].[GearSquadId]) AND [t].[GearSquadId] IS NOT NULL) AND (([g].[Nickname] = [t].[GearNickName]) AND [t].[GearNickName] IS NOT NULL) +INNER JOIN [Cities] AS [c] ON [g].[CityOrBirthName] = [c].[Name] +LEFT 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] - INNER JOIN [Cities] AS [g.CityOfBirth0] ON [g0].[CityOrBirthName] = [g.CityOfBirth0].[Name] - INNER JOIN [Tags] AS [t0] ON ([g0].[SquadId] = [t0].[GearSquadId]) AND ([g0].[Nickname] = [t0].[GearNickName]) - WHERE [g0].[Discriminator] IN (N'Officer', N'Gear') -) AS [t1] ON [g.CityOfBirth.StationedGears].[AssignedCityName] = [t1].[Name] -WHERE [g.CityOfBirth.StationedGears].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [t1].[Name]"); + WHERE [g0].[Discriminator] IN (N'Gear', N'Officer') +) AS [t0] ON [c].[Name] = [t0].[AssignedCityName] +WHERE [g].[Discriminator] IN (N'Gear', N'Officer') +ORDER BY [g].[Nickname], [g].[SquadId], [t].[Id], [c].[Name]"); } public override async Task Include_with_join_and_inheritance1(bool isAsync) @@ -473,11 +393,14 @@ public override async Task Include_with_join_and_inheritance1(bool isAsync) await base.Include_with_join_and_inheritance1(isAsync); AssertSql( - @"SELECT [o].[Nickname], [o].[SquadId], [o].[AssignedCityName], [o].[CityOrBirthName], [o].[Discriminator], [o].[FullName], [o].[HasSoulPatch], [o].[LeaderNickname], [o].[LeaderSquadId], [o].[Rank], [o.CityOfBirth].[Name], [o.CityOfBirth].[Location], [o.CityOfBirth].[Nation] -FROM [Tags] AS [t] -INNER JOIN [Gears] AS [o] ON ([t].[GearSquadId] = [o].[SquadId]) AND ([t].[GearNickName] = [o].[Nickname]) -INNER JOIN [Cities] AS [o.CityOfBirth] ON [o].[CityOrBirthName] = [o.CityOfBirth].[Name] -WHERE [o].[Discriminator] = N'Officer'"); + @"SELECT [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank], [c].[Name], [c].[Location], [c].[Nation] +FROM [Tags] AS [t0] +INNER JOIN ( + 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') AND ([g].[Discriminator] = N'Officer') +) AS [t] ON (([t0].[GearSquadId] = [t].[SquadId]) AND [t0].[GearSquadId] IS NOT NULL) AND (([t0].[GearNickName] = [t].[Nickname]) AND [t0].[GearNickName] IS NOT NULL) +INNER JOIN [Cities] AS [c] ON [t].[CityOrBirthName] = [c].[Name]"); } public override async Task Include_with_join_and_inheritance_with_orderby_before_and_after_include(bool isAsync) @@ -493,21 +416,12 @@ public override async Task Include_with_join_and_inheritance2(bool isAsync) await base.Include_with_join_and_inheritance2(isAsync); AssertSql( - @"SELECT [o].[Nickname], [o].[SquadId], [o].[AssignedCityName], [o].[CityOrBirthName], [o].[Discriminator], [o].[FullName], [o].[HasSoulPatch], [o].[LeaderNickname], [o].[LeaderSquadId], [o].[Rank] -FROM [Gears] AS [o] -INNER JOIN [Tags] AS [t] ON ([o].[SquadId] = [t].[GearSquadId]) AND ([o].[Nickname] = [t].[GearNickName]) -WHERE [o].[Discriminator] = N'Officer' -ORDER BY [o].[FullName]", - // - @"SELECT [o.Weapons].[Id], [o.Weapons].[AmmunitionType], [o.Weapons].[IsAutomatic], [o.Weapons].[Name], [o.Weapons].[OwnerFullName], [o.Weapons].[SynergyWithId] -FROM [Weapons] AS [o.Weapons] -INNER JOIN ( - SELECT DISTINCT [o0].[FullName] - FROM [Gears] AS [o0] - INNER JOIN [Tags] AS [t0] ON ([o0].[SquadId] = [t0].[GearSquadId]) AND ([o0].[Nickname] = [t0].[GearNickName]) - WHERE [o0].[Discriminator] = N'Officer' -) AS [t1] ON [o.Weapons].[OwnerFullName] = [t1].[FullName] -ORDER BY [t1].[FullName]"); + @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [t].[Id], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] +FROM [Gears] AS [g] +INNER JOIN [Tags] AS [t] ON (([g].[SquadId] = [t].[GearSquadId]) AND [t].[GearSquadId] IS NOT NULL) AND (([g].[Nickname] = [t].[GearNickName]) AND [t].[GearNickName] IS NOT NULL) +LEFT JOIN [Weapons] AS [w] ON [g].[FullName] = [w].[OwnerFullName] +WHERE [g].[Discriminator] IN (N'Gear', N'Officer') AND ([g].[Discriminator] = N'Officer') +ORDER BY [g].[Nickname], [g].[SquadId], [t].[Id]"); } public override async Task Include_with_join_and_inheritance3(bool isAsync) @@ -515,22 +429,19 @@ public override async Task Include_with_join_and_inheritance3(bool isAsync) await base.Include_with_join_and_inheritance3(isAsync); AssertSql( - @"SELECT [o].[Nickname], [o].[SquadId], [o].[AssignedCityName], [o].[CityOrBirthName], [o].[Discriminator], [o].[FullName], [o].[HasSoulPatch], [o].[LeaderNickname], [o].[LeaderSquadId], [o].[Rank] -FROM [Tags] AS [t] -INNER JOIN [Gears] AS [o] ON ([t].[GearSquadId] = [o].[SquadId]) AND ([t].[GearNickName] = [o].[Nickname]) -WHERE [o].[Discriminator] = N'Officer' -ORDER BY [o].[Nickname], [o].[SquadId]", - // - @"SELECT [o.Reports].[Nickname], [o.Reports].[SquadId], [o.Reports].[AssignedCityName], [o.Reports].[CityOrBirthName], [o.Reports].[Discriminator], [o.Reports].[FullName], [o.Reports].[HasSoulPatch], [o.Reports].[LeaderNickname], [o.Reports].[LeaderSquadId], [o.Reports].[Rank] -FROM [Gears] AS [o.Reports] + @"SELECT [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank], [t0].[Id], [t1].[Nickname], [t1].[SquadId], [t1].[AssignedCityName], [t1].[CityOrBirthName], [t1].[Discriminator], [t1].[FullName], [t1].[HasSoulPatch], [t1].[LeaderNickname], [t1].[LeaderSquadId], [t1].[Rank] +FROM [Tags] AS [t0] INNER JOIN ( - SELECT DISTINCT [o0].[Nickname], [o0].[SquadId] - FROM [Tags] AS [t0] - INNER JOIN [Gears] AS [o0] ON ([t0].[GearSquadId] = [o0].[SquadId]) AND ([t0].[GearNickName] = [o0].[Nickname]) - WHERE [o0].[Discriminator] = N'Officer' -) AS [t1] ON ([o.Reports].[LeaderNickname] = [t1].[Nickname]) AND ([o.Reports].[LeaderSquadId] = [t1].[SquadId]) -WHERE [o.Reports].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [t1].[Nickname], [t1].[SquadId]"); + 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') AND ([g].[Discriminator] = N'Officer') +) AS [t] ON (([t0].[GearSquadId] = [t].[SquadId]) AND [t0].[GearSquadId] IS NOT NULL) AND (([t0].[GearNickName] = [t].[Nickname]) AND [t0].[GearNickName] IS NOT NULL) +LEFT 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 [t1] ON (([t].[Nickname] = [t1].[LeaderNickname]) AND [t1].[LeaderNickname] IS NOT NULL) AND ([t].[SquadId] = [t1].[LeaderSquadId]) +ORDER BY [t0].[Id], [t].[Nickname], [t].[SquadId]"); } public override async Task Include_with_nested_navigation_in_order_by(bool isAsync) @@ -541,13 +452,13 @@ public override async Task Include_with_nested_navigation_in_order_by(bool isAsy @"SELECT [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank] FROM [Weapons] AS [w] LEFT JOIN ( - SELECT [w.Owner].* - FROM [Gears] AS [w.Owner] - WHERE [w.Owner].[Discriminator] IN (N'Officer', N'Gear') + 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] ON [w].[OwnerFullName] = [t].[FullName] -LEFT JOIN [Cities] AS [w.Owner.CityOfBirth] ON [t].[CityOrBirthName] = [w.Owner.CityOfBirth].[Name] +LEFT JOIN [Cities] AS [c] ON [t].[CityOrBirthName] = [c].[Name] WHERE ([t].[Nickname] <> N'Paduk') OR [t].[Nickname] IS NULL -ORDER BY [w.Owner.CityOfBirth].[Name], [w].[Id]"); +ORDER BY [c].[Name], [w].[Id]"); } public override async Task Where_enum(bool isAsync) @@ -2187,11 +2098,14 @@ public override async Task Collection_with_inheritance_and_join_include_joined(b await base.Collection_with_inheritance_and_join_include_joined(isAsync); AssertSql( - @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [g.Tag].[Id], [g.Tag].[GearNickName], [g.Tag].[GearSquadId], [g.Tag].[Note] -FROM [Tags] AS [t] -INNER JOIN [Gears] AS [g] ON ([t].[GearSquadId] = [g].[SquadId]) AND ([t].[GearNickName] = [g].[Nickname]) -LEFT JOIN [Tags] AS [g.Tag] ON ([g].[Nickname] = [g.Tag].[GearNickName]) AND ([g].[SquadId] = [g.Tag].[GearSquadId]) -WHERE [g].[Discriminator] = N'Officer'"); + @"SELECT [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank], [t0].[Id], [t0].[GearNickName], [t0].[GearSquadId], [t0].[Note] +FROM [Tags] AS [t1] +INNER JOIN ( + 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') AND ([g].[Discriminator] = N'Officer') +) AS [t] ON (([t1].[GearSquadId] = [t].[SquadId]) AND [t1].[GearSquadId] IS NOT NULL) AND (([t1].[GearNickName] = [t].[Nickname]) AND [t1].[GearNickName] IS NOT NULL) +LEFT JOIN [Tags] AS [t0] ON (([t].[Nickname] = [t0].[GearNickName]) AND [t0].[GearNickName] IS NOT NULL) AND (([t].[SquadId] = [t0].[GearSquadId]) AND [t0].[GearSquadId] IS NOT NULL)"); } public override async Task Collection_with_inheritance_and_join_include_source(bool isAsync) @@ -2199,11 +2113,11 @@ public override async Task Collection_with_inheritance_and_join_include_source(b await base.Collection_with_inheritance_and_join_include_source(isAsync); AssertSql( - @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [g.Tag].[Id], [g.Tag].[GearNickName], [g.Tag].[GearSquadId], [g.Tag].[Note] + @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [t].[Id], [t].[GearNickName], [t].[GearSquadId], [t].[Note] FROM [Gears] AS [g] -LEFT JOIN [Tags] AS [g.Tag] ON ([g].[Nickname] = [g.Tag].[GearNickName]) AND ([g].[SquadId] = [g.Tag].[GearSquadId]) -INNER JOIN [Tags] AS [t] ON ([g].[SquadId] = [t].[GearSquadId]) AND ([g].[Nickname] = [t].[GearNickName]) -WHERE [g].[Discriminator] = N'Officer'"); +INNER JOIN [Tags] AS [t0] ON (([g].[SquadId] = [t0].[GearSquadId]) AND [t0].[GearSquadId] IS NOT NULL) AND (([g].[Nickname] = [t0].[GearNickName]) AND [t0].[GearNickName] IS NOT NULL) +LEFT JOIN [Tags] AS [t] ON (([g].[Nickname] = [t].[GearNickName]) AND [t].[GearNickName] IS NOT NULL) AND (([g].[SquadId] = [t].[GearSquadId]) AND [t].[GearSquadId] IS NOT NULL) +WHERE [g].[Discriminator] IN (N'Gear', N'Officer') AND ([g].[Discriminator] = N'Officer')"); } public override async Task Non_unicode_string_literal_is_used_for_non_unicode_column(bool isAsync) @@ -3438,11 +3352,11 @@ public override async Task Any_with_optional_navigation_as_subquery_predicate_is AssertSql( @"SELECT [s].[Name] FROM [Squads] AS [s] -WHERE NOT EXISTS ( +WHERE NOT (EXISTS ( SELECT 1 FROM [Gears] AS [g] - LEFT JOIN [Tags] AS [m.Tag] ON ([g].[Nickname] = [m.Tag].[GearNickName]) AND ([g].[SquadId] = [m.Tag].[GearSquadId]) - WHERE ([g].[Discriminator] IN (N'Officer', N'Gear') AND ([s].[Id] = [g].[SquadId])) AND ([m.Tag].[Note] = N'Dom''s Tag'))"); + LEFT JOIN [Tags] AS [t] ON (([g].[Nickname] = [t].[GearNickName]) AND [t].[GearNickName] IS NOT NULL) AND (([g].[SquadId] = [t].[GearSquadId]) AND [t].[GearSquadId] IS NOT NULL) + WHERE ([g].[Discriminator] IN (N'Gear', N'Officer') AND ([s].[Id] = [g].[SquadId])) AND (([t].[Note] = N'Dom''s Tag') AND [t].[Note] IS NOT NULL)))"); } public override async Task All_with_optional_navigation_is_translated_to_sql(bool isAsync) @@ -3534,10 +3448,10 @@ public override void Where_is_properly_lifted_from_subquery_created_by_include() base.Where_is_properly_lifted_from_subquery_created_by_include(); AssertSql( - @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [g.Tag].[Id], [g.Tag].[GearNickName], [g.Tag].[GearSquadId], [g.Tag].[Note] + @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [t].[Id], [t].[GearNickName], [t].[GearSquadId], [t].[Note] FROM [Gears] AS [g] -LEFT JOIN [Tags] AS [g.Tag] ON ([g].[Nickname] = [g.Tag].[GearNickName]) AND ([g].[SquadId] = [g.Tag].[GearSquadId]) -WHERE ([g].[Discriminator] IN (N'Officer', N'Gear') AND ([g].[FullName] <> N'Augustus Cole')) AND ([g].[HasSoulPatch] = CAST(0 AS bit)) +LEFT JOIN [Tags] AS [t] ON (([g].[Nickname] = [t].[GearNickName]) AND [t].[GearNickName] IS NOT NULL) AND (([g].[SquadId] = [t].[GearSquadId]) AND [t].[GearSquadId] IS NOT NULL) +WHERE ([g].[Discriminator] IN (N'Gear', N'Officer') AND ([g].[FullName] <> N'Augustus Cole')) AND ([g].[HasSoulPatch] <> CAST(1 AS bit)) ORDER BY [g].[FullName]"); } @@ -3609,14 +3523,14 @@ public override void Subquery_created_by_include_gets_lifted_nested() base.Subquery_created_by_include_gets_lifted_nested(); AssertSql( - @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [g.CityOfBirth].[Name], [g.CityOfBirth].[Location], [g.CityOfBirth].[Nation] + @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [c].[Name], [c].[Location], [c].[Nation] FROM [Gears] AS [g] -INNER JOIN [Cities] AS [g.CityOfBirth] ON [g].[CityOrBirthName] = [g.CityOfBirth].[Name] -WHERE ([g].[Discriminator] IN (N'Officer', N'Gear') AND EXISTS ( +INNER JOIN [Cities] AS [c] ON [g].[CityOrBirthName] = [c].[Name] +WHERE ([g].[Discriminator] IN (N'Gear', N'Officer') AND EXISTS ( SELECT 1 FROM [Weapons] AS [w] - WHERE [g].[FullName] = [w].[OwnerFullName])) AND ([g].[HasSoulPatch] = CAST(0 AS bit)) -ORDER BY [g].[Nickname], [g].[Rank]"); + WHERE ([g].[FullName] = [w].[OwnerFullName]) AND [w].[OwnerFullName] IS NOT NULL)) AND ([g].[HasSoulPatch] <> CAST(1 AS bit)) +ORDER BY [g].[Nickname]"); } public override async Task Subquery_is_lifted_from_additional_from_clause(bool isAsync) @@ -4041,13 +3955,16 @@ public override void Navigation_access_via_EFProperty_on_derived_entity_using_ca base.Navigation_access_via_EFProperty_on_derived_entity_using_cast(); AssertSql( - @"SELECT [f].[Name], [t].[ThreatLevel] AS [Threat] -FROM [ConditionalFactions] AS [f] + @"SELECT [f].[Name], CAST([t].[ThreatLevel] AS smallint) AS [Threat] +FROM [Factions] 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]) + 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 CASE + WHEN [f].[Discriminator] = N'LocustHorde' THEN [f].[CommanderName] + ELSE NULL +END = [t].[Name] WHERE ([f].[Discriminator] = N'LocustHorde') AND ([f].[Discriminator] = N'LocustHorde') ORDER BY [f].[Name]"); } @@ -4108,30 +4025,20 @@ public override void Include_on_derived_entity_using_OfType() base.Include_on_derived_entity_using_OfType(); AssertSql( - @"SELECT [lh].[Id], [lh].[CapitalName], [lh].[Discriminator], [lh].[Name], [lh].[CommanderName], [lh].[Eradicated], [t].[Name], [t].[Discriminator], [t].[LocustHordeId], [t].[ThreatLevel], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId] -FROM [ConditionalFactions] AS [lh] + @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated], [t].[Name], [t].[Discriminator], [t].[LocustHordeId], [t].[ThreatLevel], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId], [t0].[Name], [t0].[Discriminator], [t0].[LocustHordeId], [t0].[ThreatLevel], [t0].[DefeatedByNickname], [t0].[DefeatedBySquadId], [t0].[HighCommandId] +FROM [Factions] AS [f] LEFT JOIN ( - SELECT [lh.Commander].* - FROM [LocustLeaders] AS [lh.Commander] - WHERE [lh.Commander].[Discriminator] = N'LocustCommander' -) AS [t] ON [lh].[CommanderName] = [t].[Name] -WHERE [lh].[Discriminator] = N'LocustHorde' -ORDER BY [lh].[Name], [lh].[Id]", - // - @"SELECT [lh.Leaders].[Name], [lh.Leaders].[Discriminator], [lh.Leaders].[LocustHordeId], [lh.Leaders].[ThreatLevel], [lh.Leaders].[DefeatedByNickname], [lh.Leaders].[DefeatedBySquadId], [lh.Leaders].[HighCommandId] -FROM [LocustLeaders] AS [lh.Leaders] -INNER JOIN ( - SELECT DISTINCT [lh0].[Id], [lh0].[Name] - FROM [ConditionalFactions] AS [lh0] - LEFT JOIN ( - SELECT [lh.Commander0].* - FROM [LocustLeaders] AS [lh.Commander0] - WHERE [lh.Commander0].[Discriminator] = N'LocustCommander' - ) AS [t0] ON [lh0].[CommanderName] = [t0].[Name] - WHERE [lh0].[Discriminator] = N'LocustHorde' -) AS [t1] ON [lh.Leaders].[LocustHordeId] = [t1].[Id] -WHERE [lh.Leaders].[Discriminator] IN (N'LocustCommander', N'LocustLeader') -ORDER BY [t1].[Name], [t1].[Id]"); + 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] +LEFT JOIN ( + SELECT [l0].[Name], [l0].[Discriminator], [l0].[LocustHordeId], [l0].[ThreatLevel], [l0].[DefeatedByNickname], [l0].[DefeatedBySquadId], [l0].[HighCommandId] + FROM [LocustLeaders] AS [l0] + WHERE [l0].[Discriminator] IN (N'LocustLeader', N'LocustCommander') +) AS [t0] ON [f].[Id] = [t0].[LocustHordeId] +WHERE ([f].[Discriminator] = N'LocustHorde') AND ([f].[Discriminator] = N'LocustHorde') +ORDER BY [f].[Name], [f].[Id]"); } public override void Include_on_derived_entity_using_subquery_with_cast() @@ -4479,27 +4386,51 @@ public override async Task Include_reference_on_derived_type_using_string(bool i @"SELECT [l].[Name], [l].[Discriminator], [l].[LocustHordeId], [l].[ThreatLevel], [l].[DefeatedByNickname], [l].[DefeatedBySquadId], [l].[HighCommandId], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank] FROM [LocustLeaders] AS [l] LEFT JOIN ( - SELECT [l.DefeatedBy].* - FROM [Gears] AS [l.DefeatedBy] - WHERE [l.DefeatedBy].[Discriminator] IN (N'Officer', N'Gear') -) AS [t] ON (([l].[Discriminator] = N'LocustCommander') AND ([l].[DefeatedByNickname] = [t].[Nickname])) AND (([l].[Discriminator] = N'LocustCommander') AND ([l].[DefeatedBySquadId] = [t].[SquadId])) -WHERE [l].[Discriminator] IN (N'LocustCommander', N'LocustLeader')"); - } - - public override async Task Include_reference_on_derived_type_using_string_nested1(bool isAsync) - { - await base.Include_reference_on_derived_type_using_string_nested1(isAsync); + 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] ON ((CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedByNickname] + ELSE NULL +END = [t].[Nickname]) AND CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedByNickname] + ELSE NULL +END IS NOT NULL) AND ((CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedBySquadId] + ELSE NULL +END = [t].[SquadId]) AND CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedBySquadId] + ELSE NULL +END IS NOT NULL) +WHERE [l].[Discriminator] IN (N'LocustLeader', N'LocustCommander')"); + } + + public override async Task Include_reference_on_derived_type_using_string_nested1(bool isAsync) + { + await base.Include_reference_on_derived_type_using_string_nested1(isAsync); AssertSql( - @"SELECT [l].[Name], [l].[Discriminator], [l].[LocustHordeId], [l].[ThreatLevel], [l].[DefeatedByNickname], [l].[DefeatedBySquadId], [l].[HighCommandId], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank], [l.DefeatedBy.Squad].[Id], [l.DefeatedBy.Squad].[InternalNumber], [l.DefeatedBy.Squad].[Name] + @"SELECT [l].[Name], [l].[Discriminator], [l].[LocustHordeId], [l].[ThreatLevel], [l].[DefeatedByNickname], [l].[DefeatedBySquadId], [l].[HighCommandId], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank], [s].[Id], [s].[InternalNumber], [s].[Name] FROM [LocustLeaders] AS [l] LEFT JOIN ( - SELECT [l.DefeatedBy].* - FROM [Gears] AS [l.DefeatedBy] - WHERE [l.DefeatedBy].[Discriminator] IN (N'Officer', N'Gear') -) AS [t] ON (([l].[Discriminator] = N'LocustCommander') AND ([l].[DefeatedByNickname] = [t].[Nickname])) AND (([l].[Discriminator] = N'LocustCommander') AND ([l].[DefeatedBySquadId] = [t].[SquadId])) -LEFT JOIN [Squads] AS [l.DefeatedBy.Squad] ON [t].[SquadId] = [l.DefeatedBy.Squad].[Id] -WHERE [l].[Discriminator] IN (N'LocustCommander', N'LocustLeader')"); + 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] ON ((CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedByNickname] + ELSE NULL +END = [t].[Nickname]) AND CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedByNickname] + ELSE NULL +END IS NOT NULL) AND ((CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedBySquadId] + ELSE NULL +END = [t].[SquadId]) AND CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedBySquadId] + ELSE NULL +END IS NOT NULL) +LEFT JOIN [Squads] AS [s] ON [t].[SquadId] = [s].[Id] +WHERE [l].[Discriminator] IN (N'LocustLeader', N'LocustCommander')"); } public override async Task Include_reference_on_derived_type_using_string_nested2(bool isAsync) @@ -4507,31 +4438,33 @@ public override async Task Include_reference_on_derived_type_using_string_nested await base.Include_reference_on_derived_type_using_string_nested2(isAsync); AssertSql( - @"SELECT [l].[Name], [l].[Discriminator], [l].[LocustHordeId], [l].[ThreatLevel], [l].[DefeatedByNickname], [l].[DefeatedBySquadId], [l].[HighCommandId], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank] + @"SELECT [l].[Name], [l].[Discriminator], [l].[LocustHordeId], [l].[ThreatLevel], [l].[DefeatedByNickname], [l].[DefeatedBySquadId], [l].[HighCommandId], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank], [t0].[Nickname], [t0].[SquadId], [t0].[AssignedCityName], [t0].[CityOrBirthName], [t0].[Discriminator], [t0].[FullName], [t0].[HasSoulPatch], [t0].[LeaderNickname], [t0].[LeaderSquadId], [t0].[Rank], [t0].[Name], [t0].[Location], [t0].[Nation] FROM [LocustLeaders] AS [l] LEFT JOIN ( - SELECT [l.DefeatedBy].* - FROM [Gears] AS [l.DefeatedBy] - WHERE [l.DefeatedBy].[Discriminator] IN (N'Officer', N'Gear') -) AS [t] ON (([l].[Discriminator] = N'LocustCommander') AND ([l].[DefeatedByNickname] = [t].[Nickname])) AND (([l].[Discriminator] = N'LocustCommander') AND ([l].[DefeatedBySquadId] = [t].[SquadId])) -WHERE [l].[Discriminator] IN (N'LocustCommander', N'LocustLeader') -ORDER BY [t].[Nickname], [t].[SquadId]", - // - @"SELECT [l.DefeatedBy.Reports].[Nickname], [l.DefeatedBy.Reports].[SquadId], [l.DefeatedBy.Reports].[AssignedCityName], [l.DefeatedBy.Reports].[CityOrBirthName], [l.DefeatedBy.Reports].[Discriminator], [l.DefeatedBy.Reports].[FullName], [l.DefeatedBy.Reports].[HasSoulPatch], [l.DefeatedBy.Reports].[LeaderNickname], [l.DefeatedBy.Reports].[LeaderSquadId], [l.DefeatedBy.Reports].[Rank], [g.CityOfBirth].[Name], [g.CityOfBirth].[Location], [g.CityOfBirth].[Nation] -FROM [Gears] AS [l.DefeatedBy.Reports] -INNER JOIN [Cities] AS [g.CityOfBirth] ON [l.DefeatedBy.Reports].[CityOrBirthName] = [g.CityOfBirth].[Name] -INNER JOIN ( - SELECT DISTINCT [t0].[Nickname], [t0].[SquadId] - FROM [LocustLeaders] AS [l0] - LEFT JOIN ( - SELECT [l.DefeatedBy0].* - FROM [Gears] AS [l.DefeatedBy0] - WHERE [l.DefeatedBy0].[Discriminator] IN (N'Officer', N'Gear') - ) AS [t0] ON (([l0].[Discriminator] = N'LocustCommander') AND ([l0].[DefeatedByNickname] = [t0].[Nickname])) AND (([l0].[Discriminator] = N'LocustCommander') AND ([l0].[DefeatedBySquadId] = [t0].[SquadId])) - WHERE [l0].[Discriminator] IN (N'LocustCommander', N'LocustLeader') -) AS [t1] ON ([l.DefeatedBy.Reports].[LeaderNickname] = [t1].[Nickname]) AND ([l.DefeatedBy.Reports].[LeaderSquadId] = [t1].[SquadId]) -WHERE [l.DefeatedBy.Reports].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [t1].[Nickname], [t1].[SquadId]"); + 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] ON ((CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedByNickname] + ELSE NULL +END = [t].[Nickname]) AND CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedByNickname] + ELSE NULL +END IS NOT NULL) AND ((CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedBySquadId] + ELSE NULL +END = [t].[SquadId]) AND CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedBySquadId] + ELSE NULL +END IS NOT NULL) +LEFT JOIN ( + SELECT [g0].[Nickname], [g0].[SquadId], [g0].[AssignedCityName], [g0].[CityOrBirthName], [g0].[Discriminator], [g0].[FullName], [g0].[HasSoulPatch], [g0].[LeaderNickname], [g0].[LeaderSquadId], [g0].[Rank], [c].[Name], [c].[Location], [c].[Nation] + FROM [Gears] AS [g0] + INNER JOIN [Cities] AS [c] ON [g0].[CityOrBirthName] = [c].[Name] + WHERE [g0].[Discriminator] IN (N'Gear', N'Officer') +) AS [t0] ON ((([t].[Nickname] = [t0].[LeaderNickname]) AND ([t].[Nickname] IS NOT NULL AND [t0].[LeaderNickname] IS NOT NULL)) OR ([t].[Nickname] IS NULL AND [t0].[LeaderNickname] IS NULL)) AND (([t].[SquadId] = [t0].[LeaderSquadId]) AND [t].[SquadId] IS NOT NULL) +WHERE [l].[Discriminator] IN (N'LocustLeader', N'LocustCommander') +ORDER BY [l].[Name]"); } public override async Task Include_reference_on_derived_type_using_lambda(bool isAsync) @@ -4539,14 +4472,26 @@ public override async Task Include_reference_on_derived_type_using_lambda(bool i await base.Include_reference_on_derived_type_using_lambda(isAsync); AssertSql( - @"SELECT [ll].[Name], [ll].[Discriminator], [ll].[LocustHordeId], [ll].[ThreatLevel], [ll].[DefeatedByNickname], [ll].[DefeatedBySquadId], [ll].[HighCommandId], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank] -FROM [LocustLeaders] AS [ll] + @"SELECT [l].[Name], [l].[Discriminator], [l].[LocustHordeId], [l].[ThreatLevel], [l].[DefeatedByNickname], [l].[DefeatedBySquadId], [l].[HighCommandId], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank] +FROM [LocustLeaders] AS [l] LEFT JOIN ( - SELECT [ll.DefeatedBy].* - FROM [Gears] AS [ll.DefeatedBy] - WHERE [ll.DefeatedBy].[Discriminator] IN (N'Officer', N'Gear') -) AS [t] ON (([ll].[Discriminator] = N'LocustCommander') AND ([ll].[DefeatedByNickname] = [t].[Nickname])) AND (([ll].[Discriminator] = N'LocustCommander') AND ([ll].[DefeatedBySquadId] = [t].[SquadId])) -WHERE [ll].[Discriminator] IN (N'LocustCommander', N'LocustLeader')"); + 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] ON ((CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedByNickname] + ELSE NULL +END = [t].[Nickname]) AND CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedByNickname] + ELSE NULL +END IS NOT NULL) AND ((CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedBySquadId] + ELSE NULL +END = [t].[SquadId]) AND CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedBySquadId] + ELSE NULL +END IS NOT NULL) +WHERE [l].[Discriminator] IN (N'LocustLeader', N'LocustCommander')"); } public override async Task Include_reference_on_derived_type_using_lambda_with_soft_cast(bool isAsync) @@ -4554,14 +4499,26 @@ public override async Task Include_reference_on_derived_type_using_lambda_with_s await base.Include_reference_on_derived_type_using_lambda_with_soft_cast(isAsync); AssertSql( - @"SELECT [ll].[Name], [ll].[Discriminator], [ll].[LocustHordeId], [ll].[ThreatLevel], [ll].[DefeatedByNickname], [ll].[DefeatedBySquadId], [ll].[HighCommandId], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank] -FROM [LocustLeaders] AS [ll] + @"SELECT [l].[Name], [l].[Discriminator], [l].[LocustHordeId], [l].[ThreatLevel], [l].[DefeatedByNickname], [l].[DefeatedBySquadId], [l].[HighCommandId], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank] +FROM [LocustLeaders] AS [l] LEFT JOIN ( - SELECT [ll.DefeatedBy].* - FROM [Gears] AS [ll.DefeatedBy] - WHERE [ll.DefeatedBy].[Discriminator] IN (N'Officer', N'Gear') -) AS [t] ON (([ll].[Discriminator] = N'LocustCommander') AND ([ll].[DefeatedByNickname] = [t].[Nickname])) AND (([ll].[Discriminator] = N'LocustCommander') AND ([ll].[DefeatedBySquadId] = [t].[SquadId])) -WHERE [ll].[Discriminator] IN (N'LocustCommander', N'LocustLeader')"); + 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] ON ((CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedByNickname] + ELSE NULL +END = [t].[Nickname]) AND CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedByNickname] + ELSE NULL +END IS NOT NULL) AND ((CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedBySquadId] + ELSE NULL +END = [t].[SquadId]) AND CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedBySquadId] + ELSE NULL +END IS NOT NULL) +WHERE [l].[Discriminator] IN (N'LocustLeader', N'LocustCommander')"); } public override async Task Include_reference_on_derived_type_using_lambda_with_tracking(bool isAsync) @@ -4572,11 +4529,23 @@ public override async Task Include_reference_on_derived_type_using_lambda_with_t @"SELECT [l].[Name], [l].[Discriminator], [l].[LocustHordeId], [l].[ThreatLevel], [l].[DefeatedByNickname], [l].[DefeatedBySquadId], [l].[HighCommandId], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank] FROM [LocustLeaders] AS [l] LEFT JOIN ( - SELECT [l.DefeatedBy].* - FROM [Gears] AS [l.DefeatedBy] - WHERE [l.DefeatedBy].[Discriminator] IN (N'Officer', N'Gear') -) AS [t] ON (([l].[Discriminator] = N'LocustCommander') AND ([l].[DefeatedByNickname] = [t].[Nickname])) AND (([l].[Discriminator] = N'LocustCommander') AND ([l].[DefeatedBySquadId] = [t].[SquadId])) -WHERE [l].[Discriminator] IN (N'LocustCommander', N'LocustLeader')"); + 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] ON ((CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedByNickname] + ELSE NULL +END = [t].[Nickname]) AND CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedByNickname] + ELSE NULL +END IS NOT NULL) AND ((CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedBySquadId] + ELSE NULL +END = [t].[SquadId]) AND CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedBySquadId] + ELSE NULL +END IS NOT NULL) +WHERE [l].[Discriminator] IN (N'LocustLeader', N'LocustCommander')"); } public override async Task Include_collection_on_derived_type_using_string(bool isAsync) @@ -4605,20 +4574,15 @@ public override async Task Include_collection_on_derived_type_using_lambda(bool await base.Include_collection_on_derived_type_using_lambda(isAsync); AssertSql( - @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] + @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank] FROM [Gears] AS [g] -WHERE [g].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [g].[Nickname], [g].[SquadId]", - // - @"SELECT [g.Reports].[Nickname], [g.Reports].[SquadId], [g.Reports].[AssignedCityName], [g.Reports].[CityOrBirthName], [g.Reports].[Discriminator], [g.Reports].[FullName], [g.Reports].[HasSoulPatch], [g.Reports].[LeaderNickname], [g.Reports].[LeaderSquadId], [g.Reports].[Rank] -FROM [Gears] AS [g.Reports] -INNER JOIN ( - SELECT [g0].[Nickname], [g0].[SquadId] +LEFT 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'Officer', N'Gear') -) AS [t] ON ([g.Reports].[LeaderNickname] = [t].[Nickname]) AND ([g.Reports].[LeaderSquadId] = [t].[SquadId]) -WHERE [g.Reports].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [t].[Nickname], [t].[SquadId]"); + WHERE [g0].[Discriminator] IN (N'Gear', N'Officer') +) AS [t] ON (([g].[Nickname] = [t].[LeaderNickname]) AND [t].[LeaderNickname] IS NOT NULL) AND ([g].[SquadId] = [t].[LeaderSquadId]) +WHERE [g].[Discriminator] IN (N'Gear', N'Officer') +ORDER BY [g].[Nickname], [g].[SquadId]"); } public override async Task Include_collection_on_derived_type_using_lambda_with_soft_cast(bool isAsync) @@ -4626,20 +4590,15 @@ public override async Task Include_collection_on_derived_type_using_lambda_with_ await base.Include_collection_on_derived_type_using_lambda_with_soft_cast(isAsync); AssertSql( - @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] + @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank] FROM [Gears] AS [g] -WHERE [g].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [g].[Nickname], [g].[SquadId]", - // - @"SELECT [g.Reports].[Nickname], [g.Reports].[SquadId], [g.Reports].[AssignedCityName], [g.Reports].[CityOrBirthName], [g.Reports].[Discriminator], [g.Reports].[FullName], [g.Reports].[HasSoulPatch], [g.Reports].[LeaderNickname], [g.Reports].[LeaderSquadId], [g.Reports].[Rank] -FROM [Gears] AS [g.Reports] -INNER JOIN ( - SELECT [g0].[Nickname], [g0].[SquadId] +LEFT 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'Officer', N'Gear') -) AS [t] ON ([g.Reports].[LeaderNickname] = [t].[Nickname]) AND ([g.Reports].[LeaderSquadId] = [t].[SquadId]) -WHERE [g.Reports].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [t].[Nickname], [t].[SquadId]"); + WHERE [g0].[Discriminator] IN (N'Gear', N'Officer') +) AS [t] ON (([g].[Nickname] = [t].[LeaderNickname]) AND [t].[LeaderNickname] IS NOT NULL) AND ([g].[SquadId] = [t].[LeaderSquadId]) +WHERE [g].[Discriminator] IN (N'Gear', N'Officer') +ORDER BY [g].[Nickname], [g].[SquadId]"); } public override async Task Include_base_navigation_on_derived_entity(bool isAsync) @@ -4647,21 +4606,12 @@ public override async Task Include_base_navigation_on_derived_entity(bool isAsyn await base.Include_base_navigation_on_derived_entity(isAsync); AssertSql( - @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [g.Tag].[Id], [g.Tag].[GearNickName], [g.Tag].[GearSquadId], [g.Tag].[Note] + @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [t].[Id], [t].[GearNickName], [t].[GearSquadId], [t].[Note], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] FROM [Gears] AS [g] -LEFT JOIN [Tags] AS [g.Tag] ON ([g].[Nickname] = [g.Tag].[GearNickName]) AND ([g].[SquadId] = [g.Tag].[GearSquadId]) -WHERE [g].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [g].[FullName]", - // - @"SELECT [g.Weapons].[Id], [g.Weapons].[AmmunitionType], [g.Weapons].[IsAutomatic], [g.Weapons].[Name], [g.Weapons].[OwnerFullName], [g.Weapons].[SynergyWithId] -FROM [Weapons] AS [g.Weapons] -INNER JOIN ( - SELECT DISTINCT [g0].[FullName] - FROM [Gears] AS [g0] - LEFT JOIN [Tags] AS [g.Tag0] ON ([g0].[Nickname] = [g.Tag0].[GearNickName]) AND ([g0].[SquadId] = [g.Tag0].[GearSquadId]) - WHERE [g0].[Discriminator] IN (N'Officer', N'Gear') -) AS [t] ON [g.Weapons].[OwnerFullName] = [t].[FullName] -ORDER BY [t].[FullName]"); +LEFT JOIN [Tags] AS [t] ON (([g].[Nickname] = [t].[GearNickName]) AND [t].[GearNickName] IS NOT NULL) AND (([g].[SquadId] = [t].[GearSquadId]) AND [t].[GearSquadId] IS NOT NULL) +LEFT JOIN [Weapons] AS [w] ON [g].[FullName] = [w].[OwnerFullName] +WHERE [g].[Discriminator] IN (N'Gear', N'Officer') +ORDER BY [g].[Nickname], [g].[SquadId]"); } public override async Task ThenInclude_collection_on_derived_after_base_reference(bool isAsync) @@ -4669,27 +4619,15 @@ public override async Task ThenInclude_collection_on_derived_after_base_referenc await base.ThenInclude_collection_on_derived_after_base_reference(isAsync); AssertSql( - @"SELECT [t].[Id], [t].[GearNickName], [t].[GearSquadId], [t].[Note], [t0].[Nickname], [t0].[SquadId], [t0].[AssignedCityName], [t0].[CityOrBirthName], [t0].[Discriminator], [t0].[FullName], [t0].[HasSoulPatch], [t0].[LeaderNickname], [t0].[LeaderSquadId], [t0].[Rank] + @"SELECT [t].[Id], [t].[GearNickName], [t].[GearSquadId], [t].[Note], [t0].[Nickname], [t0].[SquadId], [t0].[AssignedCityName], [t0].[CityOrBirthName], [t0].[Discriminator], [t0].[FullName], [t0].[HasSoulPatch], [t0].[LeaderNickname], [t0].[LeaderSquadId], [t0].[Rank], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] FROM [Tags] AS [t] LEFT JOIN ( - SELECT [t.Gear].* - FROM [Gears] AS [t.Gear] - WHERE [t.Gear].[Discriminator] IN (N'Officer', N'Gear') -) AS [t0] ON ([t].[GearNickName] = [t0].[Nickname]) AND ([t].[GearSquadId] = [t0].[SquadId]) -ORDER BY [t0].[FullName]", - // - @"SELECT [t.Gear.Weapons].[Id], [t.Gear.Weapons].[AmmunitionType], [t.Gear.Weapons].[IsAutomatic], [t.Gear.Weapons].[Name], [t.Gear.Weapons].[OwnerFullName], [t.Gear.Weapons].[SynergyWithId] -FROM [Weapons] AS [t.Gear.Weapons] -INNER JOIN ( - SELECT DISTINCT [t2].[FullName] - FROM [Tags] AS [t1] - LEFT JOIN ( - SELECT [t.Gear0].* - FROM [Gears] AS [t.Gear0] - WHERE [t.Gear0].[Discriminator] IN (N'Officer', N'Gear') - ) AS [t2] ON ([t1].[GearNickName] = [t2].[Nickname]) AND ([t1].[GearSquadId] = [t2].[SquadId]) -) AS [t3] ON [t.Gear.Weapons].[OwnerFullName] = [t3].[FullName] -ORDER BY [t3].[FullName]"); + 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 [t0] ON (([t].[GearNickName] = [t0].[Nickname]) AND [t].[GearNickName] IS NOT NULL) AND (([t].[GearSquadId] = [t0].[SquadId]) AND [t].[GearSquadId] IS NOT NULL) +LEFT JOIN [Weapons] AS [w] ON [t0].[FullName] = [w].[OwnerFullName] +ORDER BY [t].[Id]"); } public override async Task ThenInclude_collection_on_derived_after_derived_reference(bool isAsync) @@ -4697,40 +4635,28 @@ public override async Task ThenInclude_collection_on_derived_after_derived_refer await base.ThenInclude_collection_on_derived_after_derived_reference(isAsync); AssertSql( - @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated], [t].[Name], [t].[Discriminator], [t].[LocustHordeId], [t].[ThreatLevel], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId], [t0].[Nickname], [t0].[SquadId], [t0].[AssignedCityName], [t0].[CityOrBirthName], [t0].[Discriminator], [t0].[FullName], [t0].[HasSoulPatch], [t0].[LeaderNickname], [t0].[LeaderSquadId], [t0].[Rank] -FROM [ConditionalFactions] AS [f] + @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated], [t].[Name], [t].[Discriminator], [t].[LocustHordeId], [t].[ThreatLevel], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId], [t0].[Nickname], [t0].[SquadId], [t0].[AssignedCityName], [t0].[CityOrBirthName], [t0].[Discriminator], [t0].[FullName], [t0].[HasSoulPatch], [t0].[LeaderNickname], [t0].[LeaderSquadId], [t0].[Rank], [t1].[Nickname], [t1].[SquadId], [t1].[AssignedCityName], [t1].[CityOrBirthName], [t1].[Discriminator], [t1].[FullName], [t1].[HasSoulPatch], [t1].[LeaderNickname], [t1].[LeaderSquadId], [t1].[Rank] +FROM [Factions] 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]) + 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 CASE + WHEN [f].[Discriminator] = N'LocustHorde' THEN [f].[CommanderName] + ELSE NULL +END = [t].[Name] LEFT JOIN ( - SELECT [f.Commander.DefeatedBy].* - FROM [Gears] AS [f.Commander.DefeatedBy] - WHERE [f.Commander.DefeatedBy].[Discriminator] IN (N'Officer', N'Gear') -) AS [t0] ON ([t].[DefeatedByNickname] = [t0].[Nickname]) AND ([t].[DefeatedBySquadId] = [t0].[SquadId]) + 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 [t0] ON (([t].[DefeatedByNickname] = [t0].[Nickname]) AND [t].[DefeatedByNickname] IS NOT NULL) AND (([t].[DefeatedBySquadId] = [t0].[SquadId]) AND [t].[DefeatedBySquadId] IS NOT NULL) +LEFT 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 [t1] ON ((([t0].[Nickname] = [t1].[LeaderNickname]) AND ([t0].[Nickname] IS NOT NULL AND [t1].[LeaderNickname] IS NOT NULL)) OR ([t0].[Nickname] IS NULL AND [t1].[LeaderNickname] IS NULL)) AND (([t0].[SquadId] = [t1].[LeaderSquadId]) AND [t0].[SquadId] IS NOT NULL) WHERE [f].[Discriminator] = N'LocustHorde' -ORDER BY [t0].[Nickname], [t0].[SquadId]", - // - @"SELECT [f.Commander.DefeatedBy.Reports].[Nickname], [f.Commander.DefeatedBy.Reports].[SquadId], [f.Commander.DefeatedBy.Reports].[AssignedCityName], [f.Commander.DefeatedBy.Reports].[CityOrBirthName], [f.Commander.DefeatedBy.Reports].[Discriminator], [f.Commander.DefeatedBy.Reports].[FullName], [f.Commander.DefeatedBy.Reports].[HasSoulPatch], [f.Commander.DefeatedBy.Reports].[LeaderNickname], [f.Commander.DefeatedBy.Reports].[LeaderSquadId], [f.Commander.DefeatedBy.Reports].[Rank] -FROM [Gears] AS [f.Commander.DefeatedBy.Reports] -INNER JOIN ( - SELECT DISTINCT [t2].[Nickname], [t2].[SquadId] - FROM [ConditionalFactions] AS [f0] - LEFT JOIN ( - SELECT [f.Commander0].* - FROM [LocustLeaders] AS [f.Commander0] - WHERE [f.Commander0].[Discriminator] = N'LocustCommander' - ) AS [t1] ON ([f0].[Discriminator] = N'LocustHorde') AND ([f0].[CommanderName] = [t1].[Name]) - LEFT JOIN ( - SELECT [f.Commander.DefeatedBy0].* - FROM [Gears] AS [f.Commander.DefeatedBy0] - WHERE [f.Commander.DefeatedBy0].[Discriminator] IN (N'Officer', N'Gear') - ) AS [t2] ON ([t1].[DefeatedByNickname] = [t2].[Nickname]) AND ([t1].[DefeatedBySquadId] = [t2].[SquadId]) - WHERE [f0].[Discriminator] = N'LocustHorde' -) AS [t3] ON ([f.Commander.DefeatedBy.Reports].[LeaderNickname] = [t3].[Nickname]) AND ([f.Commander.DefeatedBy.Reports].[LeaderSquadId] = [t3].[SquadId]) -WHERE [f.Commander.DefeatedBy.Reports].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [t3].[Nickname], [t3].[SquadId]"); +ORDER BY [f].[Id]"); } public override async Task ThenInclude_collection_on_derived_after_derived_collection(bool isAsync) @@ -4738,35 +4664,20 @@ public override async Task ThenInclude_collection_on_derived_after_derived_colle await base.ThenInclude_collection_on_derived_after_derived_collection(isAsync); AssertSql( - @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] + @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [t0].[Nickname], [t0].[SquadId], [t0].[AssignedCityName], [t0].[CityOrBirthName], [t0].[Discriminator], [t0].[FullName], [t0].[HasSoulPatch], [t0].[LeaderNickname], [t0].[LeaderSquadId], [t0].[Rank], [t0].[Nickname0], [t0].[SquadId0], [t0].[AssignedCityName0], [t0].[CityOrBirthName0], [t0].[Discriminator0], [t0].[FullName0], [t0].[HasSoulPatch0], [t0].[LeaderNickname0], [t0].[LeaderSquadId0], [t0].[Rank0] FROM [Gears] AS [g] -WHERE [g].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [g].[Nickname], [g].[SquadId]", - // - @"SELECT [g.Reports].[Nickname], [g.Reports].[SquadId], [g.Reports].[AssignedCityName], [g.Reports].[CityOrBirthName], [g.Reports].[Discriminator], [g.Reports].[FullName], [g.Reports].[HasSoulPatch], [g.Reports].[LeaderNickname], [g.Reports].[LeaderSquadId], [g.Reports].[Rank] -FROM [Gears] AS [g.Reports] -INNER JOIN ( - SELECT [g0].[Nickname], [g0].[SquadId] +LEFT JOIN ( + SELECT [g0].[Nickname], [g0].[SquadId], [g0].[AssignedCityName], [g0].[CityOrBirthName], [g0].[Discriminator], [g0].[FullName], [g0].[HasSoulPatch], [g0].[LeaderNickname], [g0].[LeaderSquadId], [g0].[Rank], [t].[Nickname] AS [Nickname0], [t].[SquadId] AS [SquadId0], [t].[AssignedCityName] AS [AssignedCityName0], [t].[CityOrBirthName] AS [CityOrBirthName0], [t].[Discriminator] AS [Discriminator0], [t].[FullName] AS [FullName0], [t].[HasSoulPatch] AS [HasSoulPatch0], [t].[LeaderNickname] AS [LeaderNickname0], [t].[LeaderSquadId] AS [LeaderSquadId0], [t].[Rank] AS [Rank0] FROM [Gears] AS [g0] - WHERE [g0].[Discriminator] IN (N'Officer', N'Gear') -) AS [t] ON ([g.Reports].[LeaderNickname] = [t].[Nickname]) AND ([g.Reports].[LeaderSquadId] = [t].[SquadId]) -WHERE [g.Reports].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [t].[Nickname], [t].[SquadId], [g.Reports].[Nickname], [g.Reports].[SquadId]", - // - @"SELECT [g.Reports.Reports].[Nickname], [g.Reports.Reports].[SquadId], [g.Reports.Reports].[AssignedCityName], [g.Reports.Reports].[CityOrBirthName], [g.Reports.Reports].[Discriminator], [g.Reports.Reports].[FullName], [g.Reports.Reports].[HasSoulPatch], [g.Reports.Reports].[LeaderNickname], [g.Reports.Reports].[LeaderSquadId], [g.Reports.Reports].[Rank] -FROM [Gears] AS [g.Reports.Reports] -INNER JOIN ( - SELECT DISTINCT [g.Reports0].[Nickname], [g.Reports0].[SquadId], [t0].[Nickname] AS [Nickname0], [t0].[SquadId] AS [SquadId0] - FROM [Gears] AS [g.Reports0] - INNER JOIN ( - SELECT [g1].[Nickname], [g1].[SquadId] + LEFT JOIN ( + SELECT [g1].[Nickname], [g1].[SquadId], [g1].[AssignedCityName], [g1].[CityOrBirthName], [g1].[Discriminator], [g1].[FullName], [g1].[HasSoulPatch], [g1].[LeaderNickname], [g1].[LeaderSquadId], [g1].[Rank] FROM [Gears] AS [g1] - WHERE [g1].[Discriminator] IN (N'Officer', N'Gear') - ) AS [t0] ON ([g.Reports0].[LeaderNickname] = [t0].[Nickname]) AND ([g.Reports0].[LeaderSquadId] = [t0].[SquadId]) - WHERE [g.Reports0].[Discriminator] IN (N'Officer', N'Gear') -) AS [t1] ON ([g.Reports.Reports].[LeaderNickname] = [t1].[Nickname]) AND ([g.Reports.Reports].[LeaderSquadId] = [t1].[SquadId]) -WHERE [g.Reports.Reports].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [t1].[Nickname0], [t1].[SquadId0], [t1].[Nickname], [t1].[SquadId]"); + WHERE [g1].[Discriminator] IN (N'Gear', N'Officer') + ) AS [t] ON (([g0].[Nickname] = [t].[LeaderNickname]) AND [t].[LeaderNickname] IS NOT NULL) AND ([g0].[SquadId] = [t].[LeaderSquadId]) + WHERE [g0].[Discriminator] IN (N'Gear', N'Officer') +) AS [t0] ON (([g].[Nickname] = [t0].[LeaderNickname]) AND [t0].[LeaderNickname] IS NOT NULL) AND ([g].[SquadId] = [t0].[LeaderSquadId]) +WHERE [g].[Discriminator] IN (N'Gear', N'Officer') +ORDER BY [g].[Nickname], [g].[SquadId]"); } public override async Task ThenInclude_reference_on_derived_after_derived_collection(bool isAsync) @@ -4774,25 +4685,32 @@ public override async Task ThenInclude_reference_on_derived_after_derived_collec await base.ThenInclude_reference_on_derived_after_derived_collection(isAsync); AssertSql( - @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated] -FROM [ConditionalFactions] AS [f] -WHERE [f].[Discriminator] = N'LocustHorde' -ORDER BY [f].[Id]", - // - @"SELECT [f.Leaders].[Name], [f.Leaders].[Discriminator], [f.Leaders].[LocustHordeId], [f.Leaders].[ThreatLevel], [f.Leaders].[DefeatedByNickname], [f.Leaders].[DefeatedBySquadId], [f.Leaders].[HighCommandId], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank] -FROM [LocustLeaders] AS [f.Leaders] + @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated], [t0].[Name], [t0].[Discriminator], [t0].[LocustHordeId], [t0].[ThreatLevel], [t0].[DefeatedByNickname], [t0].[DefeatedBySquadId], [t0].[HighCommandId], [t0].[Nickname], [t0].[SquadId], [t0].[AssignedCityName], [t0].[CityOrBirthName], [t0].[Discriminator0], [t0].[FullName], [t0].[HasSoulPatch], [t0].[LeaderNickname], [t0].[LeaderSquadId], [t0].[Rank] +FROM [Factions] AS [f] LEFT JOIN ( - SELECT [l.DefeatedBy].* - FROM [Gears] AS [l.DefeatedBy] - WHERE [l.DefeatedBy].[Discriminator] IN (N'Officer', N'Gear') -) AS [t] ON (([f.Leaders].[Discriminator] = N'LocustCommander') AND ([f.Leaders].[DefeatedByNickname] = [t].[Nickname])) AND (([f.Leaders].[Discriminator] = N'LocustCommander') AND ([f.Leaders].[DefeatedBySquadId] = [t].[SquadId])) -INNER JOIN ( - SELECT [f0].[Id] - FROM [ConditionalFactions] AS [f0] - WHERE [f0].[Discriminator] = N'LocustHorde' -) AS [t0] ON [f.Leaders].[LocustHordeId] = [t0].[Id] -WHERE [f.Leaders].[Discriminator] IN (N'LocustCommander', N'LocustLeader') -ORDER BY [t0].[Id]"); + SELECT [l].[Name], [l].[Discriminator], [l].[LocustHordeId], [l].[ThreatLevel], [l].[DefeatedByNickname], [l].[DefeatedBySquadId], [l].[HighCommandId], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator] AS [Discriminator0], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank] + FROM [LocustLeaders] AS [l] + LEFT JOIN ( + 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] ON ((CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedByNickname] + ELSE NULL + END = [t].[Nickname]) AND CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedByNickname] + ELSE NULL + END IS NOT NULL) AND ((CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedBySquadId] + ELSE NULL + END = [t].[SquadId]) AND CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedBySquadId] + ELSE NULL + END IS NOT NULL) + WHERE [l].[Discriminator] IN (N'LocustLeader', N'LocustCommander') +) AS [t0] ON [f].[Id] = [t0].[LocustHordeId] +WHERE [f].[Discriminator] = N'LocustHorde' +ORDER BY [f].[Id]"); } public override async Task Multiple_derived_included_on_one_method(bool isAsync) @@ -4800,40 +4718,28 @@ public override async Task Multiple_derived_included_on_one_method(bool isAsync) await base.Multiple_derived_included_on_one_method(isAsync); AssertSql( - @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated], [t].[Name], [t].[Discriminator], [t].[LocustHordeId], [t].[ThreatLevel], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId], [t0].[Nickname], [t0].[SquadId], [t0].[AssignedCityName], [t0].[CityOrBirthName], [t0].[Discriminator], [t0].[FullName], [t0].[HasSoulPatch], [t0].[LeaderNickname], [t0].[LeaderSquadId], [t0].[Rank] -FROM [ConditionalFactions] AS [f] + @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated], [t].[Name], [t].[Discriminator], [t].[LocustHordeId], [t].[ThreatLevel], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId], [t0].[Nickname], [t0].[SquadId], [t0].[AssignedCityName], [t0].[CityOrBirthName], [t0].[Discriminator], [t0].[FullName], [t0].[HasSoulPatch], [t0].[LeaderNickname], [t0].[LeaderSquadId], [t0].[Rank], [t1].[Nickname], [t1].[SquadId], [t1].[AssignedCityName], [t1].[CityOrBirthName], [t1].[Discriminator], [t1].[FullName], [t1].[HasSoulPatch], [t1].[LeaderNickname], [t1].[LeaderSquadId], [t1].[Rank] +FROM [Factions] 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]) + 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 CASE + WHEN [f].[Discriminator] = N'LocustHorde' THEN [f].[CommanderName] + ELSE NULL +END = [t].[Name] LEFT JOIN ( - SELECT [f.Commander.DefeatedBy].* - FROM [Gears] AS [f.Commander.DefeatedBy] - WHERE [f.Commander.DefeatedBy].[Discriminator] IN (N'Officer', N'Gear') -) AS [t0] ON ([t].[DefeatedByNickname] = [t0].[Nickname]) AND ([t].[DefeatedBySquadId] = [t0].[SquadId]) + 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 [t0] ON (([t].[DefeatedByNickname] = [t0].[Nickname]) AND [t].[DefeatedByNickname] IS NOT NULL) AND (([t].[DefeatedBySquadId] = [t0].[SquadId]) AND [t].[DefeatedBySquadId] IS NOT NULL) +LEFT 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 [t1] ON ((([t0].[Nickname] = [t1].[LeaderNickname]) AND ([t0].[Nickname] IS NOT NULL AND [t1].[LeaderNickname] IS NOT NULL)) OR ([t0].[Nickname] IS NULL AND [t1].[LeaderNickname] IS NULL)) AND (([t0].[SquadId] = [t1].[LeaderSquadId]) AND [t0].[SquadId] IS NOT NULL) WHERE [f].[Discriminator] = N'LocustHorde' -ORDER BY [t0].[Nickname], [t0].[SquadId]", - // - @"SELECT [f.Commander.DefeatedBy.Reports].[Nickname], [f.Commander.DefeatedBy.Reports].[SquadId], [f.Commander.DefeatedBy.Reports].[AssignedCityName], [f.Commander.DefeatedBy.Reports].[CityOrBirthName], [f.Commander.DefeatedBy.Reports].[Discriminator], [f.Commander.DefeatedBy.Reports].[FullName], [f.Commander.DefeatedBy.Reports].[HasSoulPatch], [f.Commander.DefeatedBy.Reports].[LeaderNickname], [f.Commander.DefeatedBy.Reports].[LeaderSquadId], [f.Commander.DefeatedBy.Reports].[Rank] -FROM [Gears] AS [f.Commander.DefeatedBy.Reports] -INNER JOIN ( - SELECT DISTINCT [t2].[Nickname], [t2].[SquadId] - FROM [ConditionalFactions] AS [f0] - LEFT JOIN ( - SELECT [f.Commander0].* - FROM [LocustLeaders] AS [f.Commander0] - WHERE [f.Commander0].[Discriminator] = N'LocustCommander' - ) AS [t1] ON ([f0].[Discriminator] = N'LocustHorde') AND ([f0].[CommanderName] = [t1].[Name]) - LEFT JOIN ( - SELECT [f.Commander.DefeatedBy0].* - FROM [Gears] AS [f.Commander.DefeatedBy0] - WHERE [f.Commander.DefeatedBy0].[Discriminator] IN (N'Officer', N'Gear') - ) AS [t2] ON ([t1].[DefeatedByNickname] = [t2].[Nickname]) AND ([t1].[DefeatedBySquadId] = [t2].[SquadId]) - WHERE [f0].[Discriminator] = N'LocustHorde' -) AS [t3] ON ([f.Commander.DefeatedBy.Reports].[LeaderNickname] = [t3].[Nickname]) AND ([f.Commander.DefeatedBy.Reports].[LeaderSquadId] = [t3].[SquadId]) -WHERE [f.Commander.DefeatedBy.Reports].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [t3].[Nickname], [t3].[SquadId]"); +ORDER BY [f].[Id]"); } public override async Task Include_on_derived_multi_level(bool isAsync) @@ -4841,36 +4747,17 @@ public override async Task Include_on_derived_multi_level(bool isAsync) await base.Include_on_derived_multi_level(isAsync); AssertSql( - @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] + @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank], [t].[Id], [t].[InternalNumber], [t].[Name], [t].[SquadId0], [t].[MissionId] FROM [Gears] AS [g] -WHERE [g].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [g].[Nickname], [g].[SquadId]", - // - @"SELECT [g.Reports].[Nickname], [g.Reports].[SquadId], [g.Reports].[AssignedCityName], [g.Reports].[CityOrBirthName], [g.Reports].[Discriminator], [g.Reports].[FullName], [g.Reports].[HasSoulPatch], [g.Reports].[LeaderNickname], [g.Reports].[LeaderSquadId], [g.Reports].[Rank], [g.Squad].[Id], [g.Squad].[InternalNumber], [g.Squad].[Name] -FROM [Gears] AS [g.Reports] -INNER JOIN [Squads] AS [g.Squad] ON [g.Reports].[SquadId] = [g.Squad].[Id] -INNER JOIN ( - SELECT [g0].[Nickname], [g0].[SquadId] +LEFT JOIN ( + SELECT [g0].[Nickname], [g0].[SquadId], [g0].[AssignedCityName], [g0].[CityOrBirthName], [g0].[Discriminator], [g0].[FullName], [g0].[HasSoulPatch], [g0].[LeaderNickname], [g0].[LeaderSquadId], [g0].[Rank], [s].[Id], [s].[InternalNumber], [s].[Name], [s0].[SquadId] AS [SquadId0], [s0].[MissionId] FROM [Gears] AS [g0] - WHERE [g0].[Discriminator] IN (N'Officer', N'Gear') -) AS [t] ON ([g.Reports].[LeaderNickname] = [t].[Nickname]) AND ([g.Reports].[LeaderSquadId] = [t].[SquadId]) -WHERE [g.Reports].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [t].[Nickname], [t].[SquadId], [g.Squad].[Id]", - // - @"SELECT [g.Squad.Missions].[SquadId], [g.Squad.Missions].[MissionId] -FROM [SquadMissions] AS [g.Squad.Missions] -INNER JOIN ( - SELECT DISTINCT [g.Squad0].[Id], [t0].[Nickname], [t0].[SquadId] - FROM [Gears] AS [g.Reports0] - INNER JOIN [Squads] AS [g.Squad0] ON [g.Reports0].[SquadId] = [g.Squad0].[Id] - INNER JOIN ( - SELECT [g1].[Nickname], [g1].[SquadId] - FROM [Gears] AS [g1] - WHERE [g1].[Discriminator] IN (N'Officer', N'Gear') - ) AS [t0] ON ([g.Reports0].[LeaderNickname] = [t0].[Nickname]) AND ([g.Reports0].[LeaderSquadId] = [t0].[SquadId]) - WHERE [g.Reports0].[Discriminator] IN (N'Officer', N'Gear') -) AS [t1] ON [g.Squad.Missions].[SquadId] = [t1].[Id] -ORDER BY [t1].[Nickname], [t1].[SquadId], [t1].[Id]"); + INNER JOIN [Squads] AS [s] ON [g0].[SquadId] = [s].[Id] + LEFT JOIN [SquadMissions] AS [s0] ON [s].[Id] = [s0].[SquadId] + WHERE [g0].[Discriminator] IN (N'Gear', N'Officer') +) AS [t] ON (([g].[Nickname] = [t].[LeaderNickname]) AND [t].[LeaderNickname] IS NOT NULL) AND ([g].[SquadId] = [t].[LeaderSquadId]) +WHERE [g].[Discriminator] IN (N'Gear', N'Officer') +ORDER BY [g].[Nickname], [g].[SquadId]"); } public override async Task Projecting_nullable_bool_in_conditional_works(bool isAsync) @@ -6565,37 +6452,50 @@ public override async Task Include_on_derived_type_with_order_by_and_paging(bool AssertSql( @"@__p_0='10' -SELECT TOP(@__p_0) [ll].[Name], [ll].[Discriminator], [ll].[LocustHordeId], [ll].[ThreatLevel], [ll].[DefeatedByNickname], [ll].[DefeatedBySquadId], [ll].[HighCommandId], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank] -FROM [LocustLeaders] AS [ll] +SELECT [t1].[Name], [t1].[Discriminator], [t1].[LocustHordeId], [t1].[ThreatLevel], [t1].[DefeatedByNickname], [t1].[DefeatedBySquadId], [t1].[HighCommandId], [t2].[Nickname], [t2].[SquadId], [t2].[AssignedCityName], [t2].[CityOrBirthName], [t2].[Discriminator], [t2].[FullName], [t2].[HasSoulPatch], [t2].[LeaderNickname], [t2].[LeaderSquadId], [t2].[Rank], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] +FROM ( + SELECT TOP(@__p_0) [l].[Name], [l].[Discriminator], [l].[LocustHordeId], [l].[ThreatLevel], [l].[DefeatedByNickname], [l].[DefeatedBySquadId], [l].[HighCommandId], [t].[Note] + FROM [LocustLeaders] AS [l] + LEFT JOIN ( + 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 [t0] ON ((CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedByNickname] + ELSE NULL + END = [t0].[Nickname]) AND CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedByNickname] + ELSE NULL + END IS NOT NULL) AND ((CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedBySquadId] + ELSE NULL + END = [t0].[SquadId]) AND CASE + WHEN [l].[Discriminator] = N'LocustCommander' THEN [l].[DefeatedBySquadId] + ELSE NULL + END IS NOT NULL) + LEFT JOIN [Tags] AS [t] ON ((([t0].[Nickname] = [t].[GearNickName]) AND ([t0].[Nickname] IS NOT NULL AND [t].[GearNickName] IS NOT NULL)) OR ([t0].[Nickname] IS NULL AND [t].[GearNickName] IS NULL)) AND ((([t0].[SquadId] = [t].[GearSquadId]) AND ([t0].[SquadId] IS NOT NULL AND [t].[GearSquadId] IS NOT NULL)) OR ([t0].[SquadId] IS NULL AND [t].[GearSquadId] IS NULL)) + WHERE [l].[Discriminator] IN (N'LocustLeader', N'LocustCommander') + ORDER BY [t].[Note] +) AS [t1] LEFT JOIN ( - SELECT [ll.DefeatedBy].* - FROM [Gears] AS [ll.DefeatedBy] - WHERE [ll.DefeatedBy].[Discriminator] IN (N'Officer', N'Gear') -) AS [t] ON (([ll].[Discriminator] = N'LocustCommander') AND ([ll].[DefeatedByNickname] = [t].[Nickname])) AND (([ll].[Discriminator] = N'LocustCommander') AND ([ll].[DefeatedBySquadId] = [t].[SquadId])) -LEFT JOIN [Tags] AS [ll.DefeatedBy.Tag] ON (([t].[Nickname] = [ll.DefeatedBy.Tag].[GearNickName]) OR ([t].[Nickname] IS NULL AND [ll.DefeatedBy.Tag].[GearNickName] IS NULL)) AND (([t].[SquadId] = [ll.DefeatedBy.Tag].[GearSquadId]) OR ([t].[SquadId] IS NULL AND [ll.DefeatedBy.Tag].[GearSquadId] IS NULL)) -WHERE [ll].[Discriminator] IN (N'LocustCommander', N'LocustLeader') -ORDER BY [ll.DefeatedBy.Tag].[Note], [t].[FullName]", - // - @"@__p_0='10' - -SELECT [ll.DefeatedBy.Weapons].[Id], [ll.DefeatedBy.Weapons].[AmmunitionType], [ll.DefeatedBy.Weapons].[IsAutomatic], [ll.DefeatedBy.Weapons].[Name], [ll.DefeatedBy.Weapons].[OwnerFullName], [ll.DefeatedBy.Weapons].[SynergyWithId] -FROM [Weapons] AS [ll.DefeatedBy.Weapons] -INNER JOIN ( - SELECT DISTINCT [t1].* - FROM ( - SELECT TOP(@__p_0) [t0].[FullName], [ll.DefeatedBy.Tag0].[Note] - FROM [LocustLeaders] AS [ll0] - LEFT JOIN ( - SELECT [ll.DefeatedBy0].* - FROM [Gears] AS [ll.DefeatedBy0] - WHERE [ll.DefeatedBy0].[Discriminator] IN (N'Officer', N'Gear') - ) AS [t0] ON (([ll0].[Discriminator] = N'LocustCommander') AND ([ll0].[DefeatedByNickname] = [t0].[Nickname])) AND (([ll0].[Discriminator] = N'LocustCommander') AND ([ll0].[DefeatedBySquadId] = [t0].[SquadId])) - LEFT JOIN [Tags] AS [ll.DefeatedBy.Tag0] ON (([t0].[Nickname] = [ll.DefeatedBy.Tag0].[GearNickName]) OR ([t0].[Nickname] IS NULL AND [ll.DefeatedBy.Tag0].[GearNickName] IS NULL)) AND (([t0].[SquadId] = [ll.DefeatedBy.Tag0].[GearSquadId]) OR ([t0].[SquadId] IS NULL AND [ll.DefeatedBy.Tag0].[GearSquadId] IS NULL)) - WHERE [ll0].[Discriminator] IN (N'LocustCommander', N'LocustLeader') - ORDER BY [ll.DefeatedBy.Tag0].[Note], [t0].[FullName] - ) AS [t1] -) AS [t2] ON [ll.DefeatedBy.Weapons].[OwnerFullName] = [t2].[FullName] -ORDER BY [t2].[Note], [t2].[FullName]"); + 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 [t2] ON ((CASE + WHEN [t1].[Discriminator] = N'LocustCommander' THEN [t1].[DefeatedByNickname] + ELSE NULL +END = [t2].[Nickname]) AND CASE + WHEN [t1].[Discriminator] = N'LocustCommander' THEN [t1].[DefeatedByNickname] + ELSE NULL +END IS NOT NULL) AND ((CASE + WHEN [t1].[Discriminator] = N'LocustCommander' THEN [t1].[DefeatedBySquadId] + ELSE NULL +END = [t2].[SquadId]) AND CASE + WHEN [t1].[Discriminator] = N'LocustCommander' THEN [t1].[DefeatedBySquadId] + ELSE NULL +END IS NOT NULL) +LEFT JOIN [Weapons] AS [w] ON [t2].[FullName] = [w].[OwnerFullName] +ORDER BY [t1].[Note], [t1].[Name]"); } public override async Task Select_required_navigation_on_derived_type(bool isAsync) @@ -7246,18 +7146,14 @@ public override async Task Include_with_order_by_constant(bool isAsync) await base.Include_with_order_by_constant(isAsync); AssertSql( - @"SELECT [s].[Id], [s].[InternalNumber], [s].[Name] + @"SELECT [s].[Id], [s].[InternalNumber], [s].[Name], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank] FROM [Squads] AS [s] -ORDER BY [s].[Id]", - // - @"SELECT [s.Members].[Nickname], [s.Members].[SquadId], [s.Members].[AssignedCityName], [s.Members].[CityOrBirthName], [s.Members].[Discriminator], [s.Members].[FullName], [s.Members].[HasSoulPatch], [s.Members].[LeaderNickname], [s.Members].[LeaderSquadId], [s.Members].[Rank] -FROM [Gears] AS [s.Members] -INNER JOIN ( - SELECT [s0].[Id], 42 AS [c] - FROM [Squads] AS [s0] -) AS [t] ON [s.Members].[SquadId] = [t].[Id] -WHERE [s.Members].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [t].[c], [t].[Id]"); +LEFT JOIN ( + 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] ON [s].[Id] = [t].[SquadId] +ORDER BY [s].[Id]"); } public override void Include_groupby_constant() @@ -7422,28 +7318,18 @@ public override async Task Include_collection_OrderBy_aggregate(bool isAsync) await base.Include_collection_OrderBy_aggregate(isAsync); AssertSql( - @"SELECT [o].[Nickname], [o].[SquadId], [o].[AssignedCityName], [o].[CityOrBirthName], [o].[Discriminator], [o].[FullName], [o].[HasSoulPatch], [o].[LeaderNickname], [o].[LeaderSquadId], [o].[Rank] -FROM [Gears] AS [o] -WHERE [o].[Discriminator] = N'Officer' + @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank] +FROM [Gears] AS [g] +LEFT 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 [t] ON (([g].[Nickname] = [t].[LeaderNickname]) AND [t].[LeaderNickname] IS NOT NULL) AND ([g].[SquadId] = [t].[LeaderSquadId]) +WHERE [g].[Discriminator] IN (N'Gear', N'Officer') AND ([g].[Discriminator] = N'Officer') ORDER BY ( SELECT COUNT(*) FROM [Weapons] AS [w] - WHERE [o].[FullName] = [w].[OwnerFullName] -), [o].[Nickname], [o].[SquadId]", - // - @"SELECT [o.Reports].[Nickname], [o.Reports].[SquadId], [o.Reports].[AssignedCityName], [o.Reports].[CityOrBirthName], [o.Reports].[Discriminator], [o.Reports].[FullName], [o.Reports].[HasSoulPatch], [o.Reports].[LeaderNickname], [o.Reports].[LeaderSquadId], [o.Reports].[Rank] -FROM [Gears] AS [o.Reports] -INNER JOIN ( - SELECT [o0].[Nickname], [o0].[SquadId], ( - SELECT COUNT(*) - FROM [Weapons] AS [w0] - WHERE [o0].[FullName] = [w0].[OwnerFullName] - ) AS [c] - FROM [Gears] AS [o0] - WHERE [o0].[Discriminator] = N'Officer' -) AS [t] ON ([o.Reports].[LeaderNickname] = [t].[Nickname]) AND ([o.Reports].[LeaderSquadId] = [t].[SquadId]) -WHERE [o.Reports].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [t].[c], [t].[Nickname], [t].[SquadId]"); + WHERE ([g].[FullName] = [w].[OwnerFullName]) AND [w].[OwnerFullName] IS NOT NULL), [g].[Nickname], [g].[SquadId]"); } public override async Task Include_collection_with_complex_OrderBy2(bool isAsync) @@ -7451,30 +7337,19 @@ public override async Task Include_collection_with_complex_OrderBy2(bool isAsync await base.Include_collection_with_complex_OrderBy2(isAsync); AssertSql( - @"SELECT [o].[Nickname], [o].[SquadId], [o].[AssignedCityName], [o].[CityOrBirthName], [o].[Discriminator], [o].[FullName], [o].[HasSoulPatch], [o].[LeaderNickname], [o].[LeaderSquadId], [o].[Rank] -FROM [Gears] AS [o] -WHERE [o].[Discriminator] = N'Officer' + @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOrBirthName], [t].[Discriminator], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank] +FROM [Gears] AS [g] +LEFT 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 [t] ON (([g].[Nickname] = [t].[LeaderNickname]) AND [t].[LeaderNickname] IS NOT NULL) AND ([g].[SquadId] = [t].[LeaderSquadId]) +WHERE [g].[Discriminator] IN (N'Gear', N'Officer') AND ([g].[Discriminator] = N'Officer') ORDER BY ( SELECT TOP(1) [w].[IsAutomatic] FROM [Weapons] AS [w] - WHERE [o].[FullName] = [w].[OwnerFullName] - ORDER BY [w].[Id] -), [o].[Nickname], [o].[SquadId]", - // - @"SELECT [o.Reports].[Nickname], [o.Reports].[SquadId], [o.Reports].[AssignedCityName], [o.Reports].[CityOrBirthName], [o.Reports].[Discriminator], [o.Reports].[FullName], [o.Reports].[HasSoulPatch], [o.Reports].[LeaderNickname], [o.Reports].[LeaderSquadId], [o.Reports].[Rank] -FROM [Gears] AS [o.Reports] -INNER JOIN ( - SELECT [o0].[Nickname], [o0].[SquadId], ( - SELECT TOP(1) [w0].[IsAutomatic] - FROM [Weapons] AS [w0] - WHERE [o0].[FullName] = [w0].[OwnerFullName] - ORDER BY [w0].[Id] - ) AS [c] - FROM [Gears] AS [o0] - WHERE [o0].[Discriminator] = N'Officer' -) AS [t] ON ([o.Reports].[LeaderNickname] = [t].[Nickname]) AND ([o.Reports].[LeaderSquadId] = [t].[SquadId]) -WHERE [o.Reports].[Discriminator] IN (N'Officer', N'Gear') -ORDER BY [t].[c], [t].[Nickname], [t].[SquadId]"); + WHERE ([g].[FullName] = [w].[OwnerFullName]) AND [w].[OwnerFullName] IS NOT NULL + ORDER BY [w].[Id]), [g].[Nickname], [g].[SquadId]"); } public override async Task Include_collection_with_complex_OrderBy3(bool isAsync) @@ -8193,19 +8068,11 @@ public override async Task Include_collection_with_Cast_to_base(bool isAsync) await base.Include_collection_with_Cast_to_base(isAsync); AssertSql( - @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] + @"SELECT [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOrBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [w].[Id], [w].[AmmunitionType], [w].[IsAutomatic], [w].[Name], [w].[OwnerFullName], [w].[SynergyWithId] FROM [Gears] AS [g] -WHERE [g].[Discriminator] = N'Officer' -ORDER BY [g].[FullName]", - // - @"SELECT [g.Weapons].[Id], [g.Weapons].[AmmunitionType], [g.Weapons].[IsAutomatic], [g.Weapons].[Name], [g.Weapons].[OwnerFullName], [g.Weapons].[SynergyWithId] -FROM [Weapons] AS [g.Weapons] -INNER JOIN ( - SELECT [g0].[FullName] - FROM [Gears] AS [g0] - WHERE [g0].[Discriminator] = N'Officer' -) AS [t] ON [g.Weapons].[OwnerFullName] = [t].[FullName] -ORDER BY [t].[FullName]"); +LEFT JOIN [Weapons] AS [w] ON [g].[FullName] = [w].[OwnerFullName] +WHERE [g].[Discriminator] IN (N'Gear', N'Officer') AND ([g].[Discriminator] = N'Officer') +ORDER BY [g].[Nickname], [g].[SquadId]"); } public override async Task Multiple_includes_with_client_method_around_qsre_and_also_projecting_included_collection() diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/IncludeAsyncSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/IncludeAsyncSqlServerTest.cs index 4b85d516c34..d996452137a 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/IncludeAsyncSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/IncludeAsyncSqlServerTest.cs @@ -21,34 +21,22 @@ public override async Task Include_collection_order_by_subquery() await base.Include_collection_order_by_subquery(); AssertSql( - @"SELECT TOP(1) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] -FROM [Customers] AS [c] -WHERE [c].[CustomerID] = N'ALFKI' -ORDER BY ( - SELECT TOP(1) [o].[OrderDate] - FROM [Orders] AS [o] - WHERE [c].[CustomerID] = [o].[CustomerID] - ORDER BY [o].[EmployeeID] -), [c].[CustomerID]", - // - @"SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT TOP(1) [c0].[CustomerID], ( - SELECT TOP(1) [o1].[OrderDate] - FROM [Orders] AS [o1] - WHERE [c0].[CustomerID] = [o1].[CustomerID] - ORDER BY [o1].[EmployeeID] - ) AS [c] - FROM [Customers] AS [c0] - WHERE [c0].[CustomerID] = N'ALFKI' + @"SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate] +FROM ( + SELECT TOP(1) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region], ( + SELECT TOP(1) [o].[OrderDate] + FROM [Orders] AS [o] + WHERE ([c].[CustomerID] = [o].[CustomerID]) AND [o].[CustomerID] IS NOT NULL + ORDER BY [o].[EmployeeID]) AS [c] + FROM [Customers] AS [c] + WHERE [c].[CustomerID] = N'ALFKI' ORDER BY ( - SELECT TOP(1) [o0].[OrderDate] - FROM [Orders] AS [o0] - WHERE [c0].[CustomerID] = [o0].[CustomerID] - ORDER BY [o0].[EmployeeID] - ), [c0].[CustomerID] -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] + SELECT TOP(1) [o].[OrderDate] + FROM [Orders] AS [o] + WHERE ([c].[CustomerID] = [o].[CustomerID]) AND [o].[CustomerID] IS NOT NULL + ORDER BY [o].[EmployeeID]), [c].[CustomerID] +) AS [t] +LEFT JOIN [Orders] AS [o0] ON [t].[CustomerID] = [o0].[CustomerID] ORDER BY [t].[c], [t].[CustomerID]"); } @@ -57,29 +45,14 @@ public override async Task Include_collection_then_include_collection() await base.Include_collection_then_include_collection(); AssertSql( - @"SELECT [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], [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate], [t].[OrderID0], [t].[ProductID], [t].[Discount], [t].[Quantity], [t].[UnitPrice] FROM [Customers] AS [c] -ORDER BY [c].[CustomerID]", - // - @"SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT [c0].[CustomerID] - FROM [Customers] AS [c0] -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] -ORDER BY [t].[CustomerID], [c.Orders].[OrderID]", - // - @"SELECT [c.Orders.OrderDetails].[OrderID], [c.Orders.OrderDetails].[ProductID], [c.Orders.OrderDetails].[Discount], [c.Orders.OrderDetails].[Quantity], [c.Orders.OrderDetails].[UnitPrice] -FROM [Order Details] AS [c.Orders.OrderDetails] -INNER JOIN ( - SELECT DISTINCT [c.Orders0].[OrderID], [t0].[CustomerID] - FROM [Orders] AS [c.Orders0] - INNER JOIN ( - SELECT [c1].[CustomerID] - FROM [Customers] AS [c1] - ) AS [t0] ON [c.Orders0].[CustomerID] = [t0].[CustomerID] -) AS [t1] ON [c.Orders.OrderDetails].[OrderID] = [t1].[OrderID] -ORDER BY [t1].[CustomerID], [t1].[OrderID]"); +LEFT JOIN ( + SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [o0].[OrderID] AS [OrderID0], [o0].[ProductID], [o0].[Discount], [o0].[Quantity], [o0].[UnitPrice] + FROM [Orders] AS [o] + LEFT JOIN [Order Details] AS [o0] ON [o].[OrderID] = [o0].[OrderID] +) AS [t] ON [c].[CustomerID] = [t].[CustomerID] +ORDER BY [c].[CustomerID]"); } [SqlServerCondition(SqlServerCondition.SupportsOffset)] diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/IncludeSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/IncludeSqlServerTest.cs index e52374dd9a0..9ed036af2af 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/IncludeSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/IncludeSqlServerTest.cs @@ -23,18 +23,14 @@ public override void Include_list(bool useString) base.Include_list(useString); AssertSql( - @"SELECT [p].[ProductID], [p].[Discontinued], [p].[ProductName], [p].[SupplierID], [p].[UnitPrice], [p].[UnitsInStock] + @"SELECT [p].[ProductID], [p].[Discontinued], [p].[ProductName], [p].[SupplierID], [p].[UnitPrice], [p].[UnitsInStock], [t].[OrderID], [t].[ProductID], [t].[Discount], [t].[Quantity], [t].[UnitPrice], [t].[OrderID0], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate] FROM [Products] AS [p] -ORDER BY [p].[ProductID]", - // - @"SELECT [p.OrderDetails].[OrderID], [p.OrderDetails].[ProductID], [p.OrderDetails].[Discount], [p.OrderDetails].[Quantity], [p.OrderDetails].[UnitPrice], [o.Order].[OrderID], [o.Order].[CustomerID], [o.Order].[EmployeeID], [o.Order].[OrderDate] -FROM [Order Details] AS [p.OrderDetails] -INNER JOIN [Orders] AS [o.Order] ON [p.OrderDetails].[OrderID] = [o.Order].[OrderID] -INNER JOIN ( - SELECT [p0].[ProductID] - FROM [Products] AS [p0] -) AS [t] ON [p.OrderDetails].[ProductID] = [t].[ProductID] -ORDER BY [t].[ProductID]"); +LEFT JOIN ( + SELECT [o].[OrderID], [o].[ProductID], [o].[Discount], [o].[Quantity], [o].[UnitPrice], [o0].[OrderID] AS [OrderID0], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate] + FROM [Order Details] AS [o] + INNER JOIN [Orders] AS [o0] ON [o].[OrderID] = [o0].[OrderID] +) AS [t] ON [p].[ProductID] = [t].[ProductID] +ORDER BY [p].[ProductID]"); } public override void Include_reference(bool useString) @@ -42,9 +38,9 @@ public override void Include_reference(bool useString) base.Include_reference(useString); AssertSql( - @"SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [o.Customer].[CustomerID], [o.Customer].[Address], [o.Customer].[City], [o.Customer].[CompanyName], [o.Customer].[ContactName], [o.Customer].[ContactTitle], [o.Customer].[Country], [o.Customer].[Fax], [o.Customer].[Phone], [o.Customer].[PostalCode], [o.Customer].[Region] + @"SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] 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]"); } @@ -53,7 +49,12 @@ public override void Include_when_result_operator(bool useString) base.Include_when_result_operator(useString); AssertSql( - @""); + @"SELECT CASE + WHEN EXISTS ( + SELECT 1 + FROM [Customers] AS [c]) THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END"); } public override void Include_collection(bool useString) @@ -61,17 +62,10 @@ public override void Include_collection(bool useString) base.Include_collection(useString); AssertSql( - @"SELECT [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], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] FROM [Customers] AS [c] -ORDER BY [c].[CustomerID]", - // - @"SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT [c0].[CustomerID] - FROM [Customers] AS [c0] -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] -ORDER BY [t].[CustomerID]"); +LEFT JOIN [Orders] AS [o] ON [c].[CustomerID] = [o].[CustomerID] +ORDER BY [c].[CustomerID]"); } public override void Include_collection_with_last(bool useString) @@ -79,18 +73,14 @@ public override void Include_collection_with_last(bool useString) base.Include_collection_with_last(useString); AssertSql( - @"SELECT TOP(1) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] -FROM [Customers] AS [c] -ORDER BY [c].[CompanyName] DESC, [c].[CustomerID] DESC", - // - @"SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT TOP(1) [c0].[CustomerID], [c0].[CompanyName] - FROM [Customers] AS [c0] - ORDER BY [c0].[CompanyName] DESC, [c0].[CustomerID] DESC -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] -ORDER BY [t].[CompanyName] DESC, [t].[CustomerID] DESC"); + @"SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] +FROM ( + SELECT TOP(1) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] + FROM [Customers] AS [c] + ORDER BY [c].[CompanyName] DESC, [c].[CustomerID] +) AS [t] +LEFT JOIN [Orders] AS [o] ON [t].[CustomerID] = [o].[CustomerID] +ORDER BY [t].[CompanyName] DESC, [t].[CustomerID]"); } public override void Include_collection_with_last_no_orderby(bool useString) @@ -121,21 +111,14 @@ public override void Include_collection_skip_no_order_by(bool useString) AssertSql( @"@__p_0='10' -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] -ORDER BY [c].[CustomerID] -OFFSET @__p_0 ROWS", - // - @"@__p_0='10' - -SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT [c0].[CustomerID] - FROM [Customers] AS [c0] - ORDER BY [c0].[CustomerID] +SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] +FROM ( + SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] + FROM [Customers] AS [c] + ORDER BY [c].[CustomerID] OFFSET @__p_0 ROWS -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] +) AS [t] +LEFT JOIN [Orders] AS [o] ON [t].[CustomerID] = [o].[CustomerID] ORDER BY [t].[CustomerID]"); } } @@ -149,19 +132,13 @@ public override void Include_collection_take_no_order_by(bool useString) AssertSql( @"@__p_0='10' -SELECT TOP(@__p_0) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] -FROM [Customers] AS [c] -ORDER BY [c].[CustomerID]", - // - @"@__p_0='10' - -SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT TOP(@__p_0) [c0].[CustomerID] - FROM [Customers] AS [c0] - ORDER BY [c0].[CustomerID] -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] +SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] +FROM ( + SELECT TOP(@__p_0) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] + FROM [Customers] AS [c] + ORDER BY [c].[CustomerID] +) AS [t] +LEFT JOIN [Orders] AS [o] ON [t].[CustomerID] = [o].[CustomerID] ORDER BY [t].[CustomerID]"); } } @@ -176,22 +153,14 @@ public override void Include_collection_skip_take_no_order_by(bool useString) @"@__p_0='10' @__p_1='5' -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] -ORDER BY [c].[CustomerID] -OFFSET @__p_0 ROWS FETCH NEXT @__p_1 ROWS ONLY", - // - @"@__p_0='10' -@__p_1='5' - -SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT [c0].[CustomerID] - FROM [Customers] AS [c0] - ORDER BY [c0].[CustomerID] +SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] +FROM ( + SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] + FROM [Customers] AS [c] + ORDER BY [c].[CustomerID] OFFSET @__p_0 ROWS FETCH NEXT @__p_1 ROWS ONLY -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] +) AS [t] +LEFT JOIN [Orders] AS [o] ON [t].[CustomerID] = [o].[CustomerID] ORDER BY [t].[CustomerID]"); } } @@ -201,19 +170,11 @@ public override void Include_reference_and_collection(bool useString) base.Include_reference_and_collection(useString); AssertSql( - @"SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [o.Customer].[CustomerID], [o.Customer].[Address], [o.Customer].[City], [o.Customer].[CompanyName], [o.Customer].[ContactName], [o.Customer].[ContactTitle], [o.Customer].[Country], [o.Customer].[Fax], [o.Customer].[Phone], [o.Customer].[PostalCode], [o.Customer].[Region] + @"SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region], [o0].[OrderID], [o0].[ProductID], [o0].[Discount], [o0].[Quantity], [o0].[UnitPrice] FROM [Orders] AS [o] -LEFT JOIN [Customers] AS [o.Customer] ON [o].[CustomerID] = [o.Customer].[CustomerID] -ORDER BY [o].[OrderID]", - // - @"SELECT [o.OrderDetails].[OrderID], [o.OrderDetails].[ProductID], [o.OrderDetails].[Discount], [o.OrderDetails].[Quantity], [o.OrderDetails].[UnitPrice] -FROM [Order Details] AS [o.OrderDetails] -INNER JOIN ( - SELECT DISTINCT [o0].[OrderID] - FROM [Orders] AS [o0] - LEFT JOIN [Customers] AS [o.Customer0] ON [o0].[CustomerID] = [o.Customer0].[CustomerID] -) AS [t] ON [o.OrderDetails].[OrderID] = [t].[OrderID] -ORDER BY [t].[OrderID]"); +LEFT JOIN [Customers] AS [c] ON [o].[CustomerID] = [c].[CustomerID] +LEFT JOIN [Order Details] AS [o0] ON [o].[OrderID] = [o0].[OrderID] +ORDER BY [o].[OrderID]"); } public override void Include_references_multi_level(bool useString) @@ -221,10 +182,10 @@ public override void Include_references_multi_level(bool useString) base.Include_references_multi_level(useString); AssertSql( - @"SELECT [o].[OrderID], [o].[ProductID], [o].[Discount], [o].[Quantity], [o].[UnitPrice], [o.Order].[OrderID], [o.Order].[CustomerID], [o.Order].[EmployeeID], [o.Order].[OrderDate], [o.Order.Customer].[CustomerID], [o.Order.Customer].[Address], [o.Order.Customer].[City], [o.Order.Customer].[CompanyName], [o.Order.Customer].[ContactName], [o.Order.Customer].[ContactTitle], [o.Order.Customer].[Country], [o.Order.Customer].[Fax], [o.Order.Customer].[Phone], [o.Order.Customer].[PostalCode], [o.Order.Customer].[Region] + @"SELECT [o].[OrderID], [o].[ProductID], [o].[Discount], [o].[Quantity], [o].[UnitPrice], [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate], [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] FROM [Order Details] AS [o] -INNER JOIN [Orders] AS [o.Order] ON [o].[OrderID] = [o.Order].[OrderID] -LEFT JOIN [Customers] AS [o.Order.Customer] ON [o.Order].[CustomerID] = [o.Order.Customer].[CustomerID]"); +INNER JOIN [Orders] AS [o0] ON [o].[OrderID] = [o0].[OrderID] +LEFT JOIN [Customers] AS [c] ON [o0].[CustomerID] = [c].[CustomerID]"); } public override void Include_multiple_references_multi_level(bool useString) @@ -232,11 +193,11 @@ public override void Include_multiple_references_multi_level(bool useString) base.Include_multiple_references_multi_level(useString); AssertSql( - @"SELECT [od].[OrderID], [od].[ProductID], [od].[Discount], [od].[Quantity], [od].[UnitPrice], [od.Order].[OrderID], [od.Order].[CustomerID], [od.Order].[EmployeeID], [od.Order].[OrderDate], [od.Order.Customer].[CustomerID], [od.Order.Customer].[Address], [od.Order.Customer].[City], [od.Order.Customer].[CompanyName], [od.Order.Customer].[ContactName], [od.Order.Customer].[ContactTitle], [od.Order.Customer].[Country], [od.Order.Customer].[Fax], [od.Order.Customer].[Phone], [od.Order.Customer].[PostalCode], [od.Order.Customer].[Region], [od.Order.Customer.Product].[ProductID], [od.Order.Customer.Product].[Discontinued], [od.Order.Customer.Product].[ProductName], [od.Order.Customer.Product].[SupplierID], [od.Order.Customer.Product].[UnitPrice], [od.Order.Customer.Product].[UnitsInStock] -FROM [Order Details] AS [od] -INNER JOIN [Orders] AS [od.Order] ON [od].[OrderID] = [od.Order].[OrderID] -LEFT JOIN [Customers] AS [od.Order.Customer] ON [od.Order].[CustomerID] = [od.Order.Customer].[CustomerID] -INNER JOIN [Products] AS [od.Order.Customer.Product] ON [od].[ProductID] = [od.Order.Customer.Product].[ProductID]"); + @"SELECT [o].[OrderID], [o].[ProductID], [o].[Discount], [o].[Quantity], [o].[UnitPrice], [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate], [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region], [p].[ProductID], [p].[Discontinued], [p].[ProductName], [p].[SupplierID], [p].[UnitPrice], [p].[UnitsInStock] +FROM [Order Details] AS [o] +INNER JOIN [Orders] AS [o0] ON [o].[OrderID] = [o0].[OrderID] +LEFT JOIN [Customers] AS [c] ON [o0].[CustomerID] = [c].[CustomerID] +INNER JOIN [Products] AS [p] ON [o].[ProductID] = [p].[ProductID]"); } public override void Include_multiple_references_multi_level_reverse(bool useString) @@ -244,11 +205,11 @@ public override void Include_multiple_references_multi_level_reverse(bool useStr base.Include_multiple_references_multi_level_reverse(useString); AssertSql( - @"SELECT [o].[OrderID], [o].[ProductID], [o].[Discount], [o].[Quantity], [o].[UnitPrice], [o.Order].[OrderID], [o.Order].[CustomerID], [o.Order].[EmployeeID], [o.Order].[OrderDate], [o.Order.Customer].[CustomerID], [o.Order.Customer].[Address], [o.Order.Customer].[City], [o.Order.Customer].[CompanyName], [o.Order.Customer].[ContactName], [o.Order.Customer].[ContactTitle], [o.Order.Customer].[Country], [o.Order.Customer].[Fax], [o.Order.Customer].[Phone], [o.Order.Customer].[PostalCode], [o.Order.Customer].[Region], [o.Product].[ProductID], [o.Product].[Discontinued], [o.Product].[ProductName], [o.Product].[SupplierID], [o.Product].[UnitPrice], [o.Product].[UnitsInStock] + @"SELECT [o].[OrderID], [o].[ProductID], [o].[Discount], [o].[Quantity], [o].[UnitPrice], [p].[ProductID], [p].[Discontinued], [p].[ProductName], [p].[SupplierID], [p].[UnitPrice], [p].[UnitsInStock], [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate], [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] FROM [Order Details] AS [o] -INNER JOIN [Orders] AS [o.Order] ON [o].[OrderID] = [o.Order].[OrderID] -LEFT JOIN [Customers] AS [o.Order.Customer] ON [o.Order].[CustomerID] = [o.Order.Customer].[CustomerID] -INNER JOIN [Products] AS [o.Product] ON [o].[ProductID] = [o.Product].[ProductID]"); +INNER JOIN [Products] AS [p] ON [o].[ProductID] = [p].[ProductID] +INNER JOIN [Orders] AS [o0] ON [o].[OrderID] = [o0].[OrderID] +LEFT JOIN [Customers] AS [c] ON [o0].[CustomerID] = [c].[CustomerID]"); } public override void Include_references_and_collection_multi_level(bool useString) @@ -256,21 +217,12 @@ public override void Include_references_and_collection_multi_level(bool useStrin base.Include_references_and_collection_multi_level(useString); AssertSql( - @"SELECT [o].[OrderID], [o].[ProductID], [o].[Discount], [o].[Quantity], [o].[UnitPrice], [o.Order].[OrderID], [o.Order].[CustomerID], [o.Order].[EmployeeID], [o.Order].[OrderDate], [o.Order.Customer].[CustomerID], [o.Order.Customer].[Address], [o.Order.Customer].[City], [o.Order.Customer].[CompanyName], [o.Order.Customer].[ContactName], [o.Order.Customer].[ContactTitle], [o.Order.Customer].[Country], [o.Order.Customer].[Fax], [o.Order.Customer].[Phone], [o.Order.Customer].[PostalCode], [o.Order.Customer].[Region] + @"SELECT [o].[OrderID], [o].[ProductID], [o].[Discount], [o].[Quantity], [o].[UnitPrice], [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate], [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region], [o1].[OrderID], [o1].[CustomerID], [o1].[EmployeeID], [o1].[OrderDate] FROM [Order Details] AS [o] -INNER JOIN [Orders] AS [o.Order] ON [o].[OrderID] = [o.Order].[OrderID] -LEFT JOIN [Customers] AS [o.Order.Customer] ON [o.Order].[CustomerID] = [o.Order.Customer].[CustomerID] -ORDER BY [o.Order.Customer].[CustomerID]", - // - @"SELECT [o.Order.Customer.Orders].[OrderID], [o.Order.Customer.Orders].[CustomerID], [o.Order.Customer.Orders].[EmployeeID], [o.Order.Customer.Orders].[OrderDate] -FROM [Orders] AS [o.Order.Customer.Orders] -INNER JOIN ( - SELECT DISTINCT [o.Order.Customer0].[CustomerID] - FROM [Order Details] AS [o0] - INNER JOIN [Orders] AS [o.Order0] ON [o0].[OrderID] = [o.Order0].[OrderID] - LEFT JOIN [Customers] AS [o.Order.Customer0] ON [o.Order0].[CustomerID] = [o.Order.Customer0].[CustomerID] -) AS [t] ON [o.Order.Customer.Orders].[CustomerID] = [t].[CustomerID] -ORDER BY [t].[CustomerID]"); +INNER JOIN [Orders] AS [o0] ON [o].[OrderID] = [o0].[OrderID] +LEFT JOIN [Customers] AS [c] ON [o0].[CustomerID] = [c].[CustomerID] +LEFT JOIN [Orders] AS [o1] ON [c].[CustomerID] = [o1].[CustomerID] +ORDER BY [o].[OrderID], [o].[ProductID], [o0].[OrderID]"); } public override void Include_multi_level_reference_and_collection_predicate(bool useString) @@ -278,25 +230,16 @@ public override void Include_multi_level_reference_and_collection_predicate(bool base.Include_multi_level_reference_and_collection_predicate(useString); AssertSql( - @"SELECT TOP(2) [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [o.Customer].[CustomerID], [o.Customer].[Address], [o.Customer].[City], [o.Customer].[CompanyName], [o.Customer].[ContactName], [o.Customer].[ContactTitle], [o.Customer].[Country], [o.Customer].[Fax], [o.Customer].[Phone], [o.Customer].[PostalCode], [o.Customer].[Region] -FROM [Orders] AS [o] -LEFT JOIN [Customers] AS [o.Customer] ON [o].[CustomerID] = [o.Customer].[CustomerID] -WHERE [o].[OrderID] = 10248 -ORDER BY [o.Customer].[CustomerID]", - // - @"SELECT [o.Customer.Orders].[OrderID], [o.Customer.Orders].[CustomerID], [o.Customer.Orders].[EmployeeID], [o.Customer.Orders].[OrderDate] -FROM [Orders] AS [o.Customer.Orders] -INNER JOIN ( - SELECT DISTINCT [t].* - FROM ( - SELECT TOP(1) [o.Customer0].[CustomerID] - FROM [Orders] AS [o0] - LEFT JOIN [Customers] AS [o.Customer0] ON [o0].[CustomerID] = [o.Customer0].[CustomerID] - WHERE [o0].[OrderID] = 10248 - ORDER BY [o.Customer0].[CustomerID] - ) AS [t] -) AS [t0] ON [o.Customer.Orders].[CustomerID] = [t0].[CustomerID] -ORDER BY [t0].[CustomerID]"); + @"SELECT [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate], [t].[CustomerID0], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate] +FROM ( + SELECT TOP(2) [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [c].[CustomerID] AS [CustomerID0], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] + FROM [Orders] AS [o] + LEFT JOIN [Customers] AS [c] ON [o].[CustomerID] = [c].[CustomerID] + WHERE [o].[OrderID] = 10248 + ORDER BY [o].[OrderID] +) AS [t] +LEFT JOIN [Orders] AS [o0] ON [t].[CustomerID0] = [o0].[CustomerID] +ORDER BY [t].[OrderID]"); } public override void Include_multi_level_collection_and_then_include_reference_predicate(bool useString) @@ -304,20 +247,18 @@ public override void Include_multi_level_collection_and_then_include_reference_p base.Include_multi_level_collection_and_then_include_reference_predicate(useString); AssertSql( - @"SELECT TOP(2) [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] -FROM [Orders] AS [o] -WHERE [o].[OrderID] = 10248 -ORDER BY [o].[OrderID]", - // - @"SELECT [o.OrderDetails].[OrderID], [o.OrderDetails].[ProductID], [o.OrderDetails].[Discount], [o.OrderDetails].[Quantity], [o.OrderDetails].[UnitPrice], [o.Product].[ProductID], [o.Product].[Discontinued], [o.Product].[ProductName], [o.Product].[SupplierID], [o.Product].[UnitPrice], [o.Product].[UnitsInStock] -FROM [Order Details] AS [o.OrderDetails] -INNER JOIN [Products] AS [o.Product] ON [o.OrderDetails].[ProductID] = [o.Product].[ProductID] -INNER JOIN ( - SELECT TOP(1) [o0].[OrderID] - FROM [Orders] AS [o0] - WHERE [o0].[OrderID] = 10248 - ORDER BY [o0].[OrderID] -) AS [t] ON [o.OrderDetails].[OrderID] = [t].[OrderID] + @"SELECT [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate], [t0].[OrderID], [t0].[ProductID], [t0].[Discount], [t0].[Quantity], [t0].[UnitPrice], [t0].[ProductID0], [t0].[Discontinued], [t0].[ProductName], [t0].[SupplierID], [t0].[UnitPrice0], [t0].[UnitsInStock] +FROM ( + SELECT TOP(2) [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] + FROM [Orders] AS [o] + WHERE [o].[OrderID] = 10248 + ORDER BY [o].[OrderID] +) AS [t] +LEFT JOIN ( + SELECT [o0].[OrderID], [o0].[ProductID], [o0].[Discount], [o0].[Quantity], [o0].[UnitPrice], [p].[ProductID] AS [ProductID0], [p].[Discontinued], [p].[ProductName], [p].[SupplierID], [p].[UnitPrice] AS [UnitPrice0], [p].[UnitsInStock] + FROM [Order Details] AS [o0] + INNER JOIN [Products] AS [p] ON [o0].[ProductID] = [p].[ProductID] +) AS [t0] ON [t].[OrderID] = [t0].[OrderID] ORDER BY [t].[OrderID]"); } @@ -326,17 +267,10 @@ public override void Include_collection_alias_generation(bool useString) base.Include_collection_alias_generation(useString); AssertSql( - @"SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] + @"SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [o0].[OrderID], [o0].[ProductID], [o0].[Discount], [o0].[Quantity], [o0].[UnitPrice] FROM [Orders] AS [o] -ORDER BY [o].[OrderID]", - // - @"SELECT [o.OrderDetails].[OrderID], [o.OrderDetails].[ProductID], [o.OrderDetails].[Discount], [o.OrderDetails].[Quantity], [o.OrderDetails].[UnitPrice] -FROM [Order Details] AS [o.OrderDetails] -INNER JOIN ( - SELECT [o0].[OrderID] - FROM [Orders] AS [o0] -) AS [t] ON [o.OrderDetails].[OrderID] = [t].[OrderID] -ORDER BY [t].[OrderID]"); +LEFT JOIN [Order Details] AS [o0] ON [o].[OrderID] = [o0].[OrderID] +ORDER BY [o].[OrderID]"); } public override void Include_collection_order_by_collection_column(bool useString) @@ -344,34 +278,22 @@ public override void Include_collection_order_by_collection_column(bool useStrin base.Include_collection_order_by_collection_column(useString); AssertSql( - @"SELECT TOP(1) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] -FROM [Customers] AS [c] -WHERE [c].[CustomerID] LIKE N'W%' -ORDER BY ( - SELECT TOP(1) [oo].[OrderDate] - FROM [Orders] AS [oo] - WHERE [c].[CustomerID] = [oo].[CustomerID] - ORDER BY [oo].[OrderDate] DESC -) DESC, [c].[CustomerID]", - // - @"SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT TOP(1) [c0].[CustomerID], ( - SELECT TOP(1) [oo1].[OrderDate] - FROM [Orders] AS [oo1] - WHERE [c0].[CustomerID] = [oo1].[CustomerID] - ORDER BY [oo1].[OrderDate] DESC - ) AS [c] - FROM [Customers] AS [c0] - WHERE [c0].[CustomerID] LIKE N'W%' + @"SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate] +FROM ( + SELECT TOP(1) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region], ( + SELECT TOP(1) [o].[OrderDate] + FROM [Orders] AS [o] + WHERE ([c].[CustomerID] = [o].[CustomerID]) AND [o].[CustomerID] IS NOT NULL + ORDER BY [o].[OrderDate] DESC) AS [c] + FROM [Customers] AS [c] + WHERE [c].[CustomerID] LIKE N'W%' ORDER BY ( - SELECT TOP(1) [oo0].[OrderDate] - FROM [Orders] AS [oo0] - WHERE [c0].[CustomerID] = [oo0].[CustomerID] - ORDER BY [oo0].[OrderDate] DESC - ) DESC, [c0].[CustomerID] -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] + SELECT TOP(1) [o].[OrderDate] + FROM [Orders] AS [o] + WHERE ([c].[CustomerID] = [o].[CustomerID]) AND [o].[CustomerID] IS NOT NULL + ORDER BY [o].[OrderDate] DESC) DESC, [c].[CustomerID] +) AS [t] +LEFT JOIN [Orders] AS [o0] ON [t].[CustomerID] = [o0].[CustomerID] ORDER BY [t].[c] DESC, [t].[CustomerID]"); } @@ -380,17 +302,10 @@ public override void Include_collection_order_by_key(bool useString) base.Include_collection_order_by_key(useString); AssertSql( - @"SELECT [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], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] FROM [Customers] AS [c] -ORDER BY [c].[CustomerID]", - // - @"SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT [c0].[CustomerID] - FROM [Customers] AS [c0] -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] -ORDER BY [t].[CustomerID]"); +LEFT JOIN [Orders] AS [o] ON [c].[CustomerID] = [o].[CustomerID] +ORDER BY [c].[CustomerID]"); } public override void Include_collection_order_by_non_key(bool useString) @@ -398,17 +313,10 @@ public override void Include_collection_order_by_non_key(bool useString) base.Include_collection_order_by_non_key(useString); AssertSql( - @"SELECT [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], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] FROM [Customers] AS [c] -ORDER BY [c].[City], [c].[CustomerID]", - // - @"SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT [c0].[CustomerID], [c0].[City] - FROM [Customers] AS [c0] -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] -ORDER BY [t].[City], [t].[CustomerID]"); +LEFT JOIN [Orders] AS [o] ON [c].[CustomerID] = [o].[CustomerID] +ORDER BY [c].[City], [c].[CustomerID]"); } public override void Include_collection_order_by_non_key_with_take(bool useString) @@ -418,19 +326,13 @@ public override void Include_collection_order_by_non_key_with_take(bool useStrin AssertSql( @"@__p_0='10' -SELECT TOP(@__p_0) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] -FROM [Customers] AS [c] -ORDER BY [c].[ContactTitle], [c].[CustomerID]", - // - @"@__p_0='10' - -SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT TOP(@__p_0) [c0].[CustomerID], [c0].[ContactTitle] - FROM [Customers] AS [c0] - ORDER BY [c0].[ContactTitle], [c0].[CustomerID] -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] +SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] +FROM ( + SELECT TOP(@__p_0) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] + FROM [Customers] AS [c] + ORDER BY [c].[ContactTitle], [c].[CustomerID] +) AS [t] +LEFT JOIN [Orders] AS [o] ON [t].[CustomerID] = [o].[CustomerID] ORDER BY [t].[ContactTitle], [t].[CustomerID]"); } @@ -443,21 +345,14 @@ public override void Include_collection_order_by_non_key_with_skip(bool useStrin AssertSql( @"@__p_0='10' -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] -ORDER BY [c].[ContactTitle], [c].[CustomerID] -OFFSET @__p_0 ROWS", - // - @"@__p_0='10' - -SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT [c0].[CustomerID], [c0].[ContactTitle] - FROM [Customers] AS [c0] - ORDER BY [c0].[ContactTitle], [c0].[CustomerID] +SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] +FROM ( + SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] + FROM [Customers] AS [c] + ORDER BY [c].[ContactTitle], [c].[CustomerID] OFFSET @__p_0 ROWS -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] +) AS [t] +LEFT JOIN [Orders] AS [o] ON [t].[CustomerID] = [o].[CustomerID] ORDER BY [t].[ContactTitle], [t].[CustomerID]"); } } @@ -467,17 +362,13 @@ public override void Include_collection_order_by_non_key_with_first_or_default(b base.Include_collection_order_by_non_key_with_first_or_default(useString); AssertSql( - @"SELECT TOP(1) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] -FROM [Customers] AS [c] -ORDER BY [c].[CompanyName] DESC, [c].[CustomerID]", - // - @"SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT TOP(1) [c0].[CustomerID], [c0].[CompanyName] - FROM [Customers] AS [c0] - ORDER BY [c0].[CompanyName] DESC, [c0].[CustomerID] -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] + @"SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] +FROM ( + SELECT TOP(1) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] + FROM [Customers] AS [c] + ORDER BY [c].[CompanyName] DESC, [c].[CustomerID] +) AS [t] +LEFT JOIN [Orders] AS [o] ON [t].[CustomerID] = [o].[CustomerID] ORDER BY [t].[CompanyName] DESC, [t].[CustomerID]"); } @@ -486,34 +377,22 @@ public override void Include_collection_order_by_subquery(bool useString) base.Include_collection_order_by_subquery(useString); AssertSql( - @"SELECT TOP(1) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] -FROM [Customers] AS [c] -WHERE [c].[CustomerID] = N'ALFKI' -ORDER BY ( - SELECT TOP(1) [o].[OrderDate] - FROM [Orders] AS [o] - WHERE [c].[CustomerID] = [o].[CustomerID] - ORDER BY [o].[EmployeeID] -), [c].[CustomerID]", - // - @"SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT TOP(1) [c0].[CustomerID], ( - SELECT TOP(1) [o1].[OrderDate] - FROM [Orders] AS [o1] - WHERE [c0].[CustomerID] = [o1].[CustomerID] - ORDER BY [o1].[EmployeeID] - ) AS [c] - FROM [Customers] AS [c0] - WHERE [c0].[CustomerID] = N'ALFKI' + @"SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate] +FROM ( + SELECT TOP(1) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region], ( + SELECT TOP(1) [o].[OrderDate] + FROM [Orders] AS [o] + WHERE ([c].[CustomerID] = [o].[CustomerID]) AND [o].[CustomerID] IS NOT NULL + ORDER BY [o].[EmployeeID]) AS [c] + FROM [Customers] AS [c] + WHERE [c].[CustomerID] = N'ALFKI' ORDER BY ( - SELECT TOP(1) [o0].[OrderDate] - FROM [Orders] AS [o0] - WHERE [c0].[CustomerID] = [o0].[CustomerID] - ORDER BY [o0].[EmployeeID] - ), [c0].[CustomerID] -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] + SELECT TOP(1) [o].[OrderDate] + FROM [Orders] AS [o] + WHERE ([c].[CustomerID] = [o].[CustomerID]) AND [o].[CustomerID] IS NOT NULL + ORDER BY [o].[EmployeeID]), [c].[CustomerID] +) AS [t] +LEFT JOIN [Orders] AS [o0] ON [t].[CustomerID] = [o0].[CustomerID] ORDER BY [t].[c], [t].[CustomerID]"); } @@ -522,17 +401,10 @@ public override void Include_collection_as_no_tracking(bool useString) base.Include_collection_as_no_tracking(useString); AssertSql( - @"SELECT [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], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] FROM [Customers] AS [c] -ORDER BY [c].[CustomerID]", - // - @"SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT [c0].[CustomerID] - FROM [Customers] AS [c0] -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] -ORDER BY [t].[CustomerID]"); +LEFT JOIN [Orders] AS [o] ON [c].[CustomerID] = [o].[CustomerID] +ORDER BY [c].[CustomerID]"); } public override void Include_collection_principal_already_tracked(bool useString) @@ -544,19 +416,14 @@ public override void Include_collection_principal_already_tracked(bool useString FROM [Customers] AS [c] WHERE [c].[CustomerID] = N'ALFKI'", // - @"SELECT TOP(2) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] -FROM [Customers] AS [c] -WHERE [c].[CustomerID] = N'ALFKI' -ORDER BY [c].[CustomerID]", - // - @"SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT TOP(1) [c0].[CustomerID] - FROM [Customers] AS [c0] - WHERE [c0].[CustomerID] = N'ALFKI' - ORDER BY [c0].[CustomerID] -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] + @"SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] +FROM ( + SELECT TOP(2) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] + FROM [Customers] AS [c] + WHERE [c].[CustomerID] = N'ALFKI' + ORDER BY [c].[CustomerID] +) AS [t] +LEFT JOIN [Orders] AS [o] ON [t].[CustomerID] = [o].[CustomerID] ORDER BY [t].[CustomerID]"); } @@ -569,19 +436,14 @@ public override void Include_collection_principal_already_tracked_as_no_tracking FROM [Customers] AS [c] WHERE [c].[CustomerID] = N'ALFKI'", // - @"SELECT TOP(2) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] -FROM [Customers] AS [c] -WHERE [c].[CustomerID] = N'ALFKI' -ORDER BY [c].[CustomerID]", - // - @"SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT TOP(1) [c0].[CustomerID] - FROM [Customers] AS [c0] - WHERE [c0].[CustomerID] = N'ALFKI' - ORDER BY [c0].[CustomerID] -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] + @"SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] +FROM ( + SELECT TOP(2) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] + FROM [Customers] AS [c] + WHERE [c].[CustomerID] = N'ALFKI' + ORDER BY [c].[CustomerID] +) AS [t] +LEFT JOIN [Orders] AS [o] ON [t].[CustomerID] = [o].[CustomerID] ORDER BY [t].[CustomerID]"); } @@ -590,19 +452,11 @@ public override void Include_collection_with_filter(bool useString) base.Include_collection_with_filter(useString); AssertSql( - @"SELECT [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], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] FROM [Customers] AS [c] +LEFT JOIN [Orders] AS [o] ON [c].[CustomerID] = [o].[CustomerID] WHERE [c].[CustomerID] = N'ALFKI' -ORDER BY [c].[CustomerID]", - // - @"SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT [c0].[CustomerID] - FROM [Customers] AS [c0] - WHERE [c0].[CustomerID] = N'ALFKI' -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] -ORDER BY [t].[CustomerID]"); +ORDER BY [c].[CustomerID]"); } public override void Include_collection_with_filter_reordered(bool useString) @@ -610,19 +464,11 @@ public override void Include_collection_with_filter_reordered(bool useString) base.Include_collection_with_filter_reordered(useString); AssertSql( - @"SELECT [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], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] FROM [Customers] AS [c] +LEFT JOIN [Orders] AS [o] ON [c].[CustomerID] = [o].[CustomerID] WHERE [c].[CustomerID] = N'ALFKI' -ORDER BY [c].[CustomerID]", - // - @"SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT [c0].[CustomerID] - FROM [Customers] AS [c0] - WHERE [c0].[CustomerID] = N'ALFKI' -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] -ORDER BY [t].[CustomerID]"); +ORDER BY [c].[CustomerID]"); } public override void Include_collection_then_include_collection(bool useString) @@ -630,29 +476,14 @@ public override void Include_collection_then_include_collection(bool useString) base.Include_collection_then_include_collection(useString); AssertSql( - @"SELECT [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], [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate], [t].[OrderID0], [t].[ProductID], [t].[Discount], [t].[Quantity], [t].[UnitPrice] FROM [Customers] AS [c] -ORDER BY [c].[CustomerID]", - // - @"SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT [c0].[CustomerID] - FROM [Customers] AS [c0] -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] -ORDER BY [t].[CustomerID], [c.Orders].[OrderID]", - // - @"SELECT [c.Orders.OrderDetails].[OrderID], [c.Orders.OrderDetails].[ProductID], [c.Orders.OrderDetails].[Discount], [c.Orders.OrderDetails].[Quantity], [c.Orders.OrderDetails].[UnitPrice] -FROM [Order Details] AS [c.Orders.OrderDetails] -INNER JOIN ( - SELECT DISTINCT [c.Orders0].[OrderID], [t0].[CustomerID] - FROM [Orders] AS [c.Orders0] - INNER JOIN ( - SELECT [c1].[CustomerID] - FROM [Customers] AS [c1] - ) AS [t0] ON [c.Orders0].[CustomerID] = [t0].[CustomerID] -) AS [t1] ON [c.Orders.OrderDetails].[OrderID] = [t1].[OrderID] -ORDER BY [t1].[CustomerID], [t1].[OrderID]"); +LEFT JOIN ( + SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [o0].[OrderID] AS [OrderID0], [o0].[ProductID], [o0].[Discount], [o0].[Quantity], [o0].[UnitPrice] + FROM [Orders] AS [o] + LEFT JOIN [Order Details] AS [o0] ON [o].[OrderID] = [o0].[OrderID] +) AS [t] ON [c].[CustomerID] = [t].[CustomerID] +ORDER BY [c].[CustomerID]"); } public override void Include_collection_then_include_collection_then_include_reference(bool useString) @@ -660,7 +491,18 @@ public override void Include_collection_then_include_collection_then_include_ref base.Include_collection_then_include_collection_then_include_reference(useString); AssertSql( - @""); + @"SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region], [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t0].[OrderID0], [t0].[ProductID], [t0].[Discount], [t0].[Quantity], [t0].[UnitPrice], [t0].[ProductID0], [t0].[Discontinued], [t0].[ProductName], [t0].[SupplierID], [t0].[UnitPrice0], [t0].[UnitsInStock] +FROM [Customers] AS [c] +LEFT JOIN ( + SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [t].[OrderID] AS [OrderID0], [t].[ProductID], [t].[Discount], [t].[Quantity], [t].[UnitPrice], [t].[ProductID0], [t].[Discontinued], [t].[ProductName], [t].[SupplierID], [t].[UnitPrice0], [t].[UnitsInStock] + FROM [Orders] AS [o] + LEFT JOIN ( + SELECT [o0].[OrderID], [o0].[ProductID], [o0].[Discount], [o0].[Quantity], [o0].[UnitPrice], [p].[ProductID] AS [ProductID0], [p].[Discontinued], [p].[ProductName], [p].[SupplierID], [p].[UnitPrice] AS [UnitPrice0], [p].[UnitsInStock] + FROM [Order Details] AS [o0] + INNER JOIN [Products] AS [p] ON [o0].[ProductID] = [p].[ProductID] + ) AS [t] ON [o].[OrderID] = [t].[OrderID] +) AS [t0] ON [c].[CustomerID] = [t0].[CustomerID] +ORDER BY [c].[CustomerID]"); } public override void Include_collection_when_projection(bool useString) @@ -677,21 +519,12 @@ public override void Include_collection_on_join_clause_with_filter(bool useStrin base.Include_collection_on_join_clause_with_filter(useString); AssertSql( - @"SELECT [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], [o].[OrderID], [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate] FROM [Customers] AS [c] INNER JOIN [Orders] AS [o] ON [c].[CustomerID] = [o].[CustomerID] +LEFT JOIN [Orders] AS [o0] ON [c].[CustomerID] = [o0].[CustomerID] WHERE [c].[CustomerID] = N'ALFKI' -ORDER BY [c].[CustomerID]", - // - @"SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT DISTINCT [c0].[CustomerID] - FROM [Customers] AS [c0] - INNER JOIN [Orders] AS [o0] ON [c0].[CustomerID] = [o0].[CustomerID] - WHERE [c0].[CustomerID] = N'ALFKI' -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] -ORDER BY [t].[CustomerID]"); +ORDER BY [c].[CustomerID], [o].[OrderID]"); } public override void Include_collection_on_additional_from_clause_with_filter(bool useString) @@ -699,21 +532,15 @@ public override void Include_collection_on_additional_from_clause_with_filter(bo base.Include_collection_on_additional_from_clause_with_filter(useString); 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 [c1] -CROSS JOIN [Customers] AS [c] -WHERE [c].[CustomerID] = N'ALFKI' -ORDER BY [c].[CustomerID]", - // - @"SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT DISTINCT [c0].[CustomerID] - FROM [Customers] AS [c10] - CROSS JOIN [Customers] AS [c0] - WHERE [c0].[CustomerID] = N'ALFKI' -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] -ORDER BY [t].[CustomerID]"); + @"SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [c0].[CustomerID], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] +FROM [Customers] AS [c0] +CROSS 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].[CustomerID] = N'ALFKI' +) AS [t] +LEFT JOIN [Orders] AS [o] ON [t].[CustomerID] = [o].[CustomerID] +ORDER BY [c0].[CustomerID], [t].[CustomerID]"); } public override void Include_collection_on_additional_from_clause(bool useString) @@ -723,29 +550,15 @@ public override void Include_collection_on_additional_from_clause(bool useString AssertSql( @"@__p_0='5' -SELECT [c2].[CustomerID], [c2].[Address], [c2].[City], [c2].[CompanyName], [c2].[ContactName], [c2].[ContactTitle], [c2].[Country], [c2].[Fax], [c2].[Phone], [c2].[PostalCode], [c2].[Region] -FROM ( - SELECT TOP(@__p_0) [c].* - FROM [Customers] AS [c] - ORDER BY [c].[CustomerID] -) AS [t] -CROSS JOIN [Customers] AS [c2] -ORDER BY [c2].[CustomerID]", - // - @"@__p_0='5' - -SELECT [c2.Orders].[OrderID], [c2.Orders].[CustomerID], [c2.Orders].[EmployeeID], [c2.Orders].[OrderDate] -FROM [Orders] AS [c2.Orders] -INNER JOIN ( - SELECT DISTINCT [c20].[CustomerID] - FROM ( - SELECT TOP(@__p_0) [c0].* - FROM [Customers] AS [c0] - ORDER BY [c0].[CustomerID] - ) AS [t0] - CROSS JOIN [Customers] AS [c20] -) AS [t1] ON [c2.Orders].[CustomerID] = [t1].[CustomerID] -ORDER BY [t1].[CustomerID]"); +SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region], [t].[CustomerID], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] +FROM ( + SELECT TOP(@__p_0) [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 [c0] + ORDER BY [c0].[CustomerID] +) AS [t] +CROSS JOIN [Customers] AS [c] +LEFT JOIN [Orders] AS [o] ON [c].[CustomerID] = [o].[CustomerID] +ORDER BY [t].[CustomerID], [c].[CustomerID]"); } public override void Include_duplicate_collection(bool useString) @@ -755,9 +568,9 @@ public override void Include_duplicate_collection(bool useString) if (SupportsOffset) { AssertSql( - @"@__p_0='2' + @"@__p_0='2' -SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [t0].[CustomerID], [t0].[Address], [t0].[City], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Country], [t0].[Fax], [t0].[Phone], [t0].[PostalCode], [t0].[Region] +SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [t0].[CustomerID], [t0].[Address], [t0].[City], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Country], [t0].[Fax], [t0].[Phone], [t0].[PostalCode], [t0].[Region], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate] FROM ( SELECT TOP(@__p_0) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] FROM [Customers] AS [c] @@ -769,47 +582,9 @@ FROM [Customers] AS [c0] ORDER BY [c0].[CustomerID] OFFSET 2 ROWS FETCH NEXT 2 ROWS ONLY ) AS [t0] -ORDER BY [t].[CustomerID], [t0].[CustomerID]", - // - @"@__p_0='2' - -SELECT [c1.Orders].[OrderID], [c1.Orders].[CustomerID], [c1.Orders].[EmployeeID], [c1.Orders].[OrderDate] -FROM [Orders] AS [c1.Orders] -INNER JOIN ( - SELECT DISTINCT [t1].[CustomerID] - FROM ( - SELECT TOP(@__p_0) [c1].* - FROM [Customers] AS [c1] - ORDER BY [c1].[CustomerID] - ) AS [t1] - CROSS JOIN ( - SELECT [c2].* - FROM [Customers] AS [c2] - ORDER BY [c2].[CustomerID] - OFFSET 2 ROWS FETCH NEXT 2 ROWS ONLY - ) AS [t2] -) AS [t3] ON [c1.Orders].[CustomerID] = [t3].[CustomerID] -ORDER BY [t3].[CustomerID]", - // - @"@__p_0='2' - -SELECT [c2.Orders].[OrderID], [c2.Orders].[CustomerID], [c2.Orders].[EmployeeID], [c2.Orders].[OrderDate] -FROM [Orders] AS [c2.Orders] -INNER JOIN ( - SELECT DISTINCT [t5].[CustomerID], [t4].[CustomerID] AS [CustomerID0] - FROM ( - SELECT TOP(@__p_0) [c3].* - FROM [Customers] AS [c3] - ORDER BY [c3].[CustomerID] - ) AS [t4] - CROSS JOIN ( - SELECT [c4].* - FROM [Customers] AS [c4] - ORDER BY [c4].[CustomerID] - OFFSET 2 ROWS FETCH NEXT 2 ROWS ONLY - ) AS [t5] -) AS [t6] ON [c2.Orders].[CustomerID] = [t6].[CustomerID] -ORDER BY [t6].[CustomerID0], [t6].[CustomerID]"); +LEFT JOIN [Orders] AS [o] ON [t].[CustomerID] = [o].[CustomerID] +LEFT JOIN [Orders] AS [o0] ON [t0].[CustomerID] = [o0].[CustomerID] +ORDER BY [t].[CustomerID], [t0].[CustomerID]"); } } @@ -823,69 +598,25 @@ public override void Include_duplicate_collection_result_operator(bool useString @"@__p_1='1' @__p_0='2' -SELECT TOP(@__p_1) [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [t0].[CustomerID], [t0].[Address], [t0].[City], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Country], [t0].[Fax], [t0].[Phone], [t0].[PostalCode], [t0].[Region] +SELECT [t1].[CustomerID], [t1].[Address], [t1].[City], [t1].[CompanyName], [t1].[ContactName], [t1].[ContactTitle], [t1].[Country], [t1].[Fax], [t1].[Phone], [t1].[PostalCode], [t1].[Region], [t1].[CustomerID0], [t1].[Address0], [t1].[City0], [t1].[CompanyName0], [t1].[ContactName0], [t1].[ContactTitle0], [t1].[Country0], [t1].[Fax0], [t1].[Phone0], [t1].[PostalCode0], [t1].[Region0], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate] FROM ( - SELECT TOP(@__p_0) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] - FROM [Customers] AS [c] - ORDER BY [c].[CustomerID] -) AS [t] -CROSS JOIN ( - 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 [c0] - ORDER BY [c0].[CustomerID] - OFFSET 2 ROWS FETCH NEXT 2 ROWS ONLY -) AS [t0] -ORDER BY [t].[CustomerID], [t0].[CustomerID]", - // - @"@__p_1='1' -@__p_0='2' - -SELECT [c1.Orders].[OrderID], [c1.Orders].[CustomerID], [c1.Orders].[EmployeeID], [c1.Orders].[OrderDate] -FROM [Orders] AS [c1.Orders] -INNER JOIN ( - SELECT DISTINCT [t3].* - FROM ( - SELECT TOP(@__p_1) [t1].[CustomerID] - FROM ( - SELECT TOP(@__p_0) [c1].* - FROM [Customers] AS [c1] - ORDER BY [c1].[CustomerID] - ) AS [t1] - CROSS JOIN ( - SELECT [c2].* - FROM [Customers] AS [c2] - ORDER BY [c2].[CustomerID] - OFFSET 2 ROWS FETCH NEXT 2 ROWS ONLY - ) AS [t2] - ORDER BY [t1].[CustomerID] - ) AS [t3] -) AS [t4] ON [c1.Orders].[CustomerID] = [t4].[CustomerID] -ORDER BY [t4].[CustomerID]", - // - @"@__p_1='1' -@__p_0='2' - -SELECT [c2.Orders].[OrderID], [c2.Orders].[CustomerID], [c2.Orders].[EmployeeID], [c2.Orders].[OrderDate] -FROM [Orders] AS [c2.Orders] -INNER JOIN ( - SELECT DISTINCT [t7].* + SELECT TOP(@__p_1) [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [t0].[CustomerID] AS [CustomerID0], [t0].[Address] AS [Address0], [t0].[City] AS [City0], [t0].[CompanyName] AS [CompanyName0], [t0].[ContactName] AS [ContactName0], [t0].[ContactTitle] AS [ContactTitle0], [t0].[Country] AS [Country0], [t0].[Fax] AS [Fax0], [t0].[Phone] AS [Phone0], [t0].[PostalCode] AS [PostalCode0], [t0].[Region] AS [Region0] FROM ( - SELECT TOP(@__p_1) [t6].[CustomerID], [t5].[CustomerID] AS [CustomerID0] - FROM ( - SELECT TOP(@__p_0) [c3].* - FROM [Customers] AS [c3] - ORDER BY [c3].[CustomerID] - ) AS [t5] - CROSS JOIN ( - SELECT [c4].* - FROM [Customers] AS [c4] - ORDER BY [c4].[CustomerID] - OFFSET 2 ROWS FETCH NEXT 2 ROWS ONLY - ) AS [t6] - ORDER BY [t5].[CustomerID], [t6].[CustomerID] - ) AS [t7] -) AS [t8] ON [c2.Orders].[CustomerID] = [t8].[CustomerID] -ORDER BY [t8].[CustomerID0], [t8].[CustomerID]"); + SELECT TOP(@__p_0) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] + FROM [Customers] AS [c] + ORDER BY [c].[CustomerID] + ) AS [t] + CROSS JOIN ( + 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 [c0] + ORDER BY [c0].[CustomerID] + OFFSET 2 ROWS FETCH NEXT 2 ROWS ONLY + ) AS [t0] + ORDER BY [t].[CustomerID], [t0].[CustomerID] +) AS [t1] +LEFT JOIN [Orders] AS [o] ON [t1].[CustomerID] = [o].[CustomerID] +LEFT JOIN [Orders] AS [o0] ON [t1].[CustomerID0] = [o0].[CustomerID] +ORDER BY [t1].[CustomerID], [t1].[CustomerID0]"); } } @@ -894,21 +625,12 @@ public override void Include_collection_on_join_clause_with_order_by_and_filter( base.Include_collection_on_join_clause_with_order_by_and_filter(useString); AssertSql( - @"SELECT [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], [o].[OrderID], [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate] FROM [Customers] AS [c] INNER JOIN [Orders] AS [o] ON [c].[CustomerID] = [o].[CustomerID] +LEFT JOIN [Orders] AS [o0] ON [c].[CustomerID] = [o0].[CustomerID] WHERE [c].[CustomerID] = N'ALFKI' -ORDER BY [c].[City], [c].[CustomerID]", - // - @"SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT DISTINCT [c0].[CustomerID], [c0].[City] - FROM [Customers] AS [c0] - INNER JOIN [Orders] AS [o0] ON [c0].[CustomerID] = [o0].[CustomerID] - WHERE [c0].[CustomerID] = N'ALFKI' -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] -ORDER BY [t].[City], [t].[CustomerID]"); +ORDER BY [c].[City], [c].[CustomerID], [o].[OrderID]"); } public override void Include_collection_when_groupby(bool useString) @@ -980,7 +702,8 @@ SELECT TOP(@__p_0) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName FROM [Customers] AS [c] ORDER BY [c].[CustomerID] ) AS [t] -CROSS JOIN [Customers] AS [c2]"); +CROSS JOIN [Customers] AS [c0] +ORDER BY [t].[CustomerID]"); } public override void Include_where_skip_take_projection(bool useString) @@ -993,11 +716,11 @@ public override void Include_where_skip_take_projection(bool useString) @"@__p_0='1' @__p_1='2' -SELECT [od.Order].[CustomerID] -FROM [Order Details] AS [od] -INNER JOIN [Orders] AS [od.Order] ON [od].[OrderID] = [od.Order].[OrderID] -WHERE [od].[Quantity] = CAST(10 AS smallint) -ORDER BY [od].[OrderID], [od].[ProductID] +SELECT [o].[CustomerID] +FROM [Order Details] AS [o0] +INNER JOIN [Orders] AS [o] ON [o0].[OrderID] = [o].[OrderID] +WHERE [o0].[Quantity] = CAST(10 AS smallint) +ORDER BY [o0].[OrderID], [o0].[ProductID] OFFSET @__p_0 ROWS FETCH NEXT @__p_1 ROWS ONLY"); } } @@ -1012,44 +735,24 @@ public override void Include_duplicate_collection_result_operator2(bool useStrin @"@__p_1='1' @__p_0='2' -SELECT TOP(@__p_1) [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [t0].[CustomerID], [t0].[Address], [t0].[City], [t0].[CompanyName], [t0].[ContactName], [t0].[ContactTitle], [t0].[Country], [t0].[Fax], [t0].[Phone], [t0].[PostalCode], [t0].[Region] +SELECT [t1].[CustomerID], [t1].[Address], [t1].[City], [t1].[CompanyName], [t1].[ContactName], [t1].[ContactTitle], [t1].[Country], [t1].[Fax], [t1].[Phone], [t1].[PostalCode], [t1].[Region], [t1].[CustomerID0], [t1].[Address0], [t1].[City0], [t1].[CompanyName0], [t1].[ContactName0], [t1].[ContactTitle0], [t1].[Country0], [t1].[Fax0], [t1].[Phone0], [t1].[PostalCode0], [t1].[Region0], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] FROM ( - SELECT TOP(@__p_0) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] - FROM [Customers] AS [c] - ORDER BY [c].[CustomerID] -) AS [t] -CROSS JOIN ( - 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 [c0] - ORDER BY [c0].[CustomerID] - OFFSET 2 ROWS FETCH NEXT 2 ROWS ONLY -) AS [t0] -ORDER BY [t].[CustomerID]", - // - @"@__p_1='1' -@__p_0='2' - -SELECT [c1.Orders].[OrderID], [c1.Orders].[CustomerID], [c1.Orders].[EmployeeID], [c1.Orders].[OrderDate] -FROM [Orders] AS [c1.Orders] -INNER JOIN ( - SELECT DISTINCT [t3].* + SELECT TOP(@__p_1) [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [t0].[CustomerID] AS [CustomerID0], [t0].[Address] AS [Address0], [t0].[City] AS [City0], [t0].[CompanyName] AS [CompanyName0], [t0].[ContactName] AS [ContactName0], [t0].[ContactTitle] AS [ContactTitle0], [t0].[Country] AS [Country0], [t0].[Fax] AS [Fax0], [t0].[Phone] AS [Phone0], [t0].[PostalCode] AS [PostalCode0], [t0].[Region] AS [Region0] FROM ( - SELECT TOP(@__p_1) [t1].[CustomerID] - FROM ( - SELECT TOP(@__p_0) [c1].* - FROM [Customers] AS [c1] - ORDER BY [c1].[CustomerID] - ) AS [t1] - CROSS JOIN ( - SELECT [c2].* - FROM [Customers] AS [c2] - ORDER BY [c2].[CustomerID] - OFFSET 2 ROWS FETCH NEXT 2 ROWS ONLY - ) AS [t2] - ORDER BY [t1].[CustomerID] - ) AS [t3] -) AS [t4] ON [c1.Orders].[CustomerID] = [t4].[CustomerID] -ORDER BY [t4].[CustomerID]"); + SELECT TOP(@__p_0) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] + FROM [Customers] AS [c] + ORDER BY [c].[CustomerID] + ) AS [t] + CROSS JOIN ( + 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 [c0] + ORDER BY [c0].[CustomerID] + OFFSET 2 ROWS FETCH NEXT 2 ROWS ONLY + ) AS [t0] + ORDER BY [t].[CustomerID], [t0].[CustomerID] +) AS [t1] +LEFT JOIN [Orders] AS [o] ON [t1].[CustomerID] = [o].[CustomerID] +ORDER BY [t1].[CustomerID], [t1].[CustomerID0]"); } } @@ -1058,10 +761,10 @@ public override void Include_multiple_references(bool useString) base.Include_multiple_references(useString); AssertSql( - @"SELECT [od].[OrderID], [od].[ProductID], [od].[Discount], [od].[Quantity], [od].[UnitPrice], [od.Order].[OrderID], [od.Order].[CustomerID], [od.Order].[EmployeeID], [od.Order].[OrderDate], [od.Order.Product].[ProductID], [od.Order.Product].[Discontinued], [od.Order.Product].[ProductName], [od.Order.Product].[SupplierID], [od.Order.Product].[UnitPrice], [od.Order.Product].[UnitsInStock] -FROM [Order Details] AS [od] -INNER JOIN [Orders] AS [od.Order] ON [od].[OrderID] = [od.Order].[OrderID] -INNER JOIN [Products] AS [od.Order.Product] ON [od].[ProductID] = [od.Order.Product].[ProductID]"); + @"SELECT [o].[OrderID], [o].[ProductID], [o].[Discount], [o].[Quantity], [o].[UnitPrice], [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate], [p].[ProductID], [p].[Discontinued], [p].[ProductName], [p].[SupplierID], [p].[UnitPrice], [p].[UnitsInStock] +FROM [Order Details] AS [o] +INNER JOIN [Orders] AS [o0] ON [o].[OrderID] = [o0].[OrderID] +INNER JOIN [Products] AS [p] ON [o].[ProductID] = [p].[ProductID]"); } public override void Include_reference_alias_generation(bool useString) @@ -1069,9 +772,9 @@ public override void Include_reference_alias_generation(bool useString) base.Include_reference_alias_generation(useString); AssertSql( - @"SELECT [o].[OrderID], [o].[ProductID], [o].[Discount], [o].[Quantity], [o].[UnitPrice], [o.Order].[OrderID], [o.Order].[CustomerID], [o.Order].[EmployeeID], [o.Order].[OrderDate] + @"SELECT [o].[OrderID], [o].[ProductID], [o].[Discount], [o].[Quantity], [o].[UnitPrice], [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate] FROM [Order Details] AS [o] -INNER JOIN [Orders] AS [o.Order] ON [o].[OrderID] = [o.Order].[OrderID]"); +INNER JOIN [Orders] AS [o0] ON [o].[OrderID] = [o0].[OrderID]"); } public override void Include_duplicate_reference(bool useString) @@ -1083,20 +786,21 @@ public override void Include_duplicate_reference(bool useString) AssertSql( @"@__p_0='2' -SELECT [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate], [o1.Customer].[CustomerID], [o1.Customer].[Address], [o1.Customer].[City], [o1.Customer].[CompanyName], [o1.Customer].[ContactName], [o1.Customer].[ContactTitle], [o1.Customer].[Country], [o1.Customer].[Fax], [o1.Customer].[Phone], [o1.Customer].[PostalCode], [o1.Customer].[Region], [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [o2.Customer].[CustomerID], [o2.Customer].[Address], [o2.Customer].[City], [o2.Customer].[CompanyName], [o2.Customer].[ContactName], [o2.Customer].[ContactTitle], [o2.Customer].[Country], [o2.Customer].[Fax], [o2.Customer].[Phone], [o2.Customer].[PostalCode], [o2.Customer].[Region] +SELECT [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate], [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region], [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [c0].[CustomerID], [c0].[Address], [c0].[City], [c0].[CompanyName], [c0].[ContactName], [c0].[ContactTitle], [c0].[Country], [c0].[Fax], [c0].[Phone], [c0].[PostalCode], [c0].[Region] FROM ( SELECT TOP(@__p_0) [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] FROM [Orders] AS [o] ORDER BY [o].[CustomerID], [o].[OrderID] ) AS [t] -LEFT JOIN [Customers] AS [o1.Customer] ON [t].[CustomerID] = [o1.Customer].[CustomerID] CROSS JOIN ( SELECT [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate] FROM [Orders] AS [o0] ORDER BY [o0].[CustomerID], [o0].[OrderID] OFFSET 2 ROWS FETCH NEXT 2 ROWS ONLY ) AS [t0] -LEFT JOIN [Customers] AS [o2.Customer] ON [t0].[CustomerID] = [o2.Customer].[CustomerID]"); +LEFT JOIN [Customers] AS [c] ON [t].[CustomerID] = [c].[CustomerID] +LEFT JOIN [Customers] AS [c0] ON [t0].[CustomerID] = [c0].[CustomerID] +ORDER BY [t].[CustomerID], [t].[OrderID]"); } } @@ -1109,19 +813,20 @@ public override void Include_duplicate_reference2(bool useString) AssertSql( @"@__p_0='2' -SELECT [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate], [o1.Customer].[CustomerID], [o1.Customer].[Address], [o1.Customer].[City], [o1.Customer].[CompanyName], [o1.Customer].[ContactName], [o1.Customer].[ContactTitle], [o1.Customer].[Country], [o1.Customer].[Fax], [o1.Customer].[Phone], [o1.Customer].[PostalCode], [o1.Customer].[Region], [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate] +SELECT [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate], [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region], [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate] FROM ( SELECT TOP(@__p_0) [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] FROM [Orders] AS [o] ORDER BY [o].[OrderID] ) AS [t] -LEFT JOIN [Customers] AS [o1.Customer] ON [t].[CustomerID] = [o1.Customer].[CustomerID] CROSS JOIN ( SELECT [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate] FROM [Orders] AS [o0] ORDER BY [o0].[OrderID] OFFSET 2 ROWS FETCH NEXT 2 ROWS ONLY -) AS [t0]"); +) AS [t0] +LEFT JOIN [Customers] AS [c] ON [t].[CustomerID] = [c].[CustomerID] +ORDER BY [t].[OrderID]"); } } @@ -1134,7 +839,7 @@ public override void Include_duplicate_reference3(bool useString) AssertSql( @"@__p_0='2' -SELECT [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate], [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [o2.Customer].[CustomerID], [o2.Customer].[Address], [o2.Customer].[City], [o2.Customer].[CompanyName], [o2.Customer].[ContactName], [o2.Customer].[ContactTitle], [o2.Customer].[Country], [o2.Customer].[Fax], [o2.Customer].[Phone], [o2.Customer].[PostalCode], [o2.Customer].[Region] +SELECT [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate], [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] FROM ( SELECT TOP(@__p_0) [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] FROM [Orders] AS [o] @@ -1146,7 +851,8 @@ FROM [Orders] AS [o0] ORDER BY [o0].[OrderID] OFFSET 2 ROWS FETCH NEXT 2 ROWS ONLY ) AS [t0] -LEFT JOIN [Customers] AS [o2.Customer] ON [t0].[CustomerID] = [o2.Customer].[CustomerID]"); +LEFT JOIN [Customers] AS [c] ON [t0].[CustomerID] = [c].[CustomerID] +ORDER BY [t].[OrderID]"); } } @@ -1164,10 +870,10 @@ public override void Include_reference_with_filter_reordered(bool useString) base.Include_reference_with_filter_reordered(useString); AssertSql( - @"SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [o.Customer].[CustomerID], [o.Customer].[Address], [o.Customer].[City], [o.Customer].[CompanyName], [o.Customer].[ContactName], [o.Customer].[ContactTitle], [o.Customer].[Country], [o.Customer].[Fax], [o.Customer].[Phone], [o.Customer].[PostalCode], [o.Customer].[Region] + @"SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] FROM [Orders] AS [o] -LEFT JOIN [Customers] AS [o.Customer] ON [o].[CustomerID] = [o.Customer].[CustomerID] -WHERE [o].[CustomerID] = N'ALFKI'"); +LEFT JOIN [Customers] AS [c] ON [o].[CustomerID] = [c].[CustomerID] +WHERE ([o].[CustomerID] = N'ALFKI') AND [o].[CustomerID] IS NOT NULL"); } public override void Include_reference_with_filter(bool useString) @@ -1175,10 +881,10 @@ public override void Include_reference_with_filter(bool useString) base.Include_reference_with_filter(useString); AssertSql( - @"SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [o.Customer].[CustomerID], [o.Customer].[Address], [o.Customer].[City], [o.Customer].[CompanyName], [o.Customer].[ContactName], [o.Customer].[ContactTitle], [o.Customer].[Country], [o.Customer].[Fax], [o.Customer].[Phone], [o.Customer].[PostalCode], [o.Customer].[Region] + @"SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] FROM [Orders] AS [o] -LEFT JOIN [Customers] AS [o.Customer] ON [o].[CustomerID] = [o.Customer].[CustomerID] -WHERE [o].[CustomerID] = N'ALFKI'"); +LEFT JOIN [Customers] AS [c] ON [o].[CustomerID] = [c].[CustomerID] +WHERE ([o].[CustomerID] = N'ALFKI') AND [o].[CustomerID] IS NOT NULL"); } public override void Include_collection_dependent_already_tracked_as_no_tracking(bool useString) @@ -1188,21 +894,16 @@ public override void Include_collection_dependent_already_tracked_as_no_tracking AssertSql( @"SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] FROM [Orders] AS [o] -WHERE [o].[CustomerID] = N'ALFKI'", - // - @"SELECT TOP(2) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] -FROM [Customers] AS [c] -WHERE [c].[CustomerID] = N'ALFKI' -ORDER BY [c].[CustomerID]", +WHERE ([o].[CustomerID] = N'ALFKI') AND [o].[CustomerID] IS NOT NULL", // - @"SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT TOP(1) [c0].[CustomerID] - FROM [Customers] AS [c0] - WHERE [c0].[CustomerID] = N'ALFKI' - ORDER BY [c0].[CustomerID] -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] + @"SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] +FROM ( + SELECT TOP(2) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] + FROM [Customers] AS [c] + WHERE [c].[CustomerID] = N'ALFKI' + ORDER BY [c].[CustomerID] +) AS [t] +LEFT JOIN [Orders] AS [o] ON [t].[CustomerID] = [o].[CustomerID] ORDER BY [t].[CustomerID]"); } @@ -1213,21 +914,16 @@ public override void Include_collection_dependent_already_tracked(bool useString AssertSql( @"SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] FROM [Orders] AS [o] -WHERE [o].[CustomerID] = N'ALFKI'", - // - @"SELECT TOP(2) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] -FROM [Customers] AS [c] -WHERE [c].[CustomerID] = N'ALFKI' -ORDER BY [c].[CustomerID]", +WHERE ([o].[CustomerID] = N'ALFKI') AND [o].[CustomerID] IS NOT NULL", // - @"SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT TOP(1) [c0].[CustomerID] - FROM [Customers] AS [c0] - WHERE [c0].[CustomerID] = N'ALFKI' - ORDER BY [c0].[CustomerID] -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] + @"SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] +FROM ( + SELECT TOP(2) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] + FROM [Customers] AS [c] + WHERE [c].[CustomerID] = N'ALFKI' + ORDER BY [c].[CustomerID] +) AS [t] +LEFT JOIN [Orders] AS [o] ON [t].[CustomerID] = [o].[CustomerID] ORDER BY [t].[CustomerID]"); } @@ -1238,11 +934,11 @@ public override void Include_reference_dependent_already_tracked(bool useString) AssertSql( @"SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] FROM [Orders] AS [o] -WHERE [o].[CustomerID] = N'ALFKI'", +WHERE ([o].[CustomerID] = N'ALFKI') AND [o].[CustomerID] IS NOT NULL", // - @"SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [o.Customer].[CustomerID], [o.Customer].[Address], [o.Customer].[City], [o.Customer].[CompanyName], [o.Customer].[ContactName], [o.Customer].[ContactTitle], [o.Customer].[Country], [o.Customer].[Fax], [o.Customer].[Phone], [o.Customer].[PostalCode], [o.Customer].[Region] + @"SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] 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]"); } public override void Include_reference_as_no_tracking(bool useString) @@ -1250,9 +946,9 @@ public override void Include_reference_as_no_tracking(bool useString) base.Include_reference_as_no_tracking(useString); AssertSql( - @"SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [o.Customer].[CustomerID], [o.Customer].[Address], [o.Customer].[City], [o.Customer].[CompanyName], [o.Customer].[ContactName], [o.Customer].[ContactTitle], [o.Customer].[Country], [o.Customer].[Fax], [o.Customer].[Phone], [o.Customer].[PostalCode], [o.Customer].[Region] + @"SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] 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]"); } public override void Include_collection_as_no_tracking2(bool useString) @@ -1262,19 +958,13 @@ public override void Include_collection_as_no_tracking2(bool useString) AssertSql( @"@__p_0='5' -SELECT TOP(@__p_0) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] -FROM [Customers] AS [c] -ORDER BY [c].[CustomerID]", - // - @"@__p_0='5' - -SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT TOP(@__p_0) [c0].[CustomerID] - FROM [Customers] AS [c0] - ORDER BY [c0].[CustomerID] -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] +SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] +FROM ( + SELECT TOP(@__p_0) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] + FROM [Customers] AS [c] + ORDER BY [c].[CustomerID] +) AS [t] +LEFT JOIN [Orders] AS [o] ON [t].[CustomerID] = [o].[CustomerID] ORDER BY [t].[CustomerID]"); } @@ -1283,8 +973,9 @@ public override void Include_with_complex_projection(bool useString) base.Include_with_complex_projection(useString); AssertSql( - @"SELECT [o].[CustomerID] AS [Id] -FROM [Orders] AS [o]"); + @"SELECT [c].[CustomerID] AS [Id] +FROM [Orders] AS [o] +LEFT JOIN [Customers] AS [c] ON [o].[CustomerID] = [c].[CustomerID]"); } public override void Include_with_complex_projection_does_not_change_ordering_of_projection(bool useString) @@ -1294,16 +985,14 @@ public override void Include_with_complex_projection_does_not_change_ordering_of AssertSql( @"SELECT [c].[CustomerID] AS [Id], ( SELECT COUNT(*) - FROM [Orders] AS [o0] - WHERE [c].[CustomerID] = [o0].[CustomerID] -) AS [TotalOrders] + FROM [Orders] AS [o] + WHERE ([c].[CustomerID] = [o].[CustomerID]) AND [o].[CustomerID] IS NOT NULL) AS [TotalOrders] FROM [Customers] AS [c] -WHERE ([c].[ContactTitle] = N'Owner') AND (( +WHERE (([c].[ContactTitle] = N'Owner') AND [c].[ContactTitle] IS NOT NULL) AND (( SELECT COUNT(*) - FROM [Orders] AS [o] - WHERE [c].[CustomerID] = [o].[CustomerID] -) > 2) -ORDER BY [Id]"); + FROM [Orders] AS [o0] + WHERE ([c].[CustomerID] = [o0].[CustomerID]) AND [o0].[CustomerID] IS NOT NULL) > 2) +ORDER BY [c].[CustomerID]"); } public override void Include_with_take(bool useString) @@ -1313,19 +1002,13 @@ public override void Include_with_take(bool useString) AssertSql( @"@__p_0='10' -SELECT TOP(@__p_0) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] -FROM [Customers] AS [c] -ORDER BY [c].[City] DESC, [c].[CustomerID]", - // - @"@__p_0='10' - -SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT TOP(@__p_0) [c0].[CustomerID], [c0].[City] - FROM [Customers] AS [c0] - ORDER BY [c0].[City] DESC, [c0].[CustomerID] -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] +SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] +FROM ( + SELECT TOP(@__p_0) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] + FROM [Customers] AS [c] + ORDER BY [c].[City] DESC, [c].[CustomerID] +) AS [t] +LEFT JOIN [Orders] AS [o] ON [t].[CustomerID] = [o].[CustomerID] ORDER BY [t].[City] DESC, [t].[CustomerID]"); } @@ -1338,21 +1021,14 @@ public override void Include_with_skip(bool useString) AssertSql( @"@__p_0='80' -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] -ORDER BY [c].[ContactName], [c].[CustomerID] -OFFSET @__p_0 ROWS", - // - @"@__p_0='80' - -SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT [c0].[CustomerID], [c0].[ContactName] - FROM [Customers] AS [c0] - ORDER BY [c0].[ContactName], [c0].[CustomerID] +SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] +FROM ( + SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] + FROM [Customers] AS [c] + ORDER BY [c].[ContactName], [c].[CustomerID] OFFSET @__p_0 ROWS -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] +) AS [t] +LEFT JOIN [Orders] AS [o] ON [t].[CustomerID] = [o].[CustomerID] ORDER BY [t].[ContactName], [t].[CustomerID]"); } } @@ -1362,59 +1038,27 @@ public override void Then_include_collection_order_by_collection_column(bool use base.Then_include_collection_order_by_collection_column(useString); AssertSql( - @"SELECT TOP(1) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] -FROM [Customers] AS [c] -WHERE [c].[CustomerID] LIKE N'W%' -ORDER BY ( - SELECT TOP(1) [oo].[OrderDate] - FROM [Orders] AS [oo] - WHERE [c].[CustomerID] = [oo].[CustomerID] - ORDER BY [oo].[OrderDate] DESC -) DESC, [c].[CustomerID]", - // - @"SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT TOP(1) [c0].[CustomerID], ( - SELECT TOP(1) [oo1].[OrderDate] - FROM [Orders] AS [oo1] - WHERE [c0].[CustomerID] = [oo1].[CustomerID] - ORDER BY [oo1].[OrderDate] DESC - ) AS [c] - FROM [Customers] AS [c0] - WHERE [c0].[CustomerID] LIKE N'W%' + @"SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [t0].[OrderID], [t0].[CustomerID], [t0].[EmployeeID], [t0].[OrderDate], [t0].[OrderID0], [t0].[ProductID], [t0].[Discount], [t0].[Quantity], [t0].[UnitPrice] +FROM ( + SELECT TOP(1) [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region], ( + SELECT TOP(1) [o].[OrderDate] + FROM [Orders] AS [o] + WHERE ([c].[CustomerID] = [o].[CustomerID]) AND [o].[CustomerID] IS NOT NULL + ORDER BY [o].[OrderDate] DESC) AS [c] + FROM [Customers] AS [c] + WHERE [c].[CustomerID] LIKE N'W%' ORDER BY ( - SELECT TOP(1) [oo0].[OrderDate] - FROM [Orders] AS [oo0] - WHERE [c0].[CustomerID] = [oo0].[CustomerID] - ORDER BY [oo0].[OrderDate] DESC - ) DESC, [c0].[CustomerID] -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] -ORDER BY [t].[c] DESC, [t].[CustomerID], [c.Orders].[OrderID]", - // - @"SELECT [c.Orders.OrderDetails].[OrderID], [c.Orders.OrderDetails].[ProductID], [c.Orders.OrderDetails].[Discount], [c.Orders.OrderDetails].[Quantity], [c.Orders.OrderDetails].[UnitPrice] -FROM [Order Details] AS [c.Orders.OrderDetails] -INNER JOIN ( - SELECT DISTINCT [c.Orders0].[OrderID], [t0].[c], [t0].[CustomerID] - FROM [Orders] AS [c.Orders0] - INNER JOIN ( - SELECT TOP(1) [c1].[CustomerID], ( - SELECT TOP(1) [oo3].[OrderDate] - FROM [Orders] AS [oo3] - WHERE [c1].[CustomerID] = [oo3].[CustomerID] - ORDER BY [oo3].[OrderDate] DESC - ) AS [c] - FROM [Customers] AS [c1] - WHERE [c1].[CustomerID] LIKE N'W%' - ORDER BY ( - SELECT TOP(1) [oo2].[OrderDate] - FROM [Orders] AS [oo2] - WHERE [c1].[CustomerID] = [oo2].[CustomerID] - ORDER BY [oo2].[OrderDate] DESC - ) DESC, [c1].[CustomerID] - ) AS [t0] ON [c.Orders0].[CustomerID] = [t0].[CustomerID] -) AS [t1] ON [c.Orders.OrderDetails].[OrderID] = [t1].[OrderID] -ORDER BY [t1].[c] DESC, [t1].[CustomerID], [t1].[OrderID]"); + SELECT TOP(1) [o].[OrderDate] + FROM [Orders] AS [o] + WHERE ([c].[CustomerID] = [o].[CustomerID]) AND [o].[CustomerID] IS NOT NULL + ORDER BY [o].[OrderDate] DESC) DESC, [c].[CustomerID] +) AS [t] +LEFT JOIN ( + SELECT [o0].[OrderID], [o0].[CustomerID], [o0].[EmployeeID], [o0].[OrderDate], [o1].[OrderID] AS [OrderID0], [o1].[ProductID], [o1].[Discount], [o1].[Quantity], [o1].[UnitPrice] + FROM [Orders] AS [o0] + LEFT JOIN [Order Details] AS [o1] ON [o0].[OrderID] = [o1].[OrderID] +) AS [t0] ON [t].[CustomerID] = [t0].[CustomerID] +ORDER BY [t].[c] DESC, [t].[CustomerID]"); } public override void Include_collection_with_conditional_order_by(bool useString) @@ -1422,23 +1066,13 @@ public override void Include_collection_with_conditional_order_by(bool useString base.Include_collection_with_conditional_order_by(useString); AssertSql( - @"SELECT [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], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] FROM [Customers] AS [c] +LEFT JOIN [Orders] AS [o] ON [c].[CustomerID] = [o].[CustomerID] ORDER BY CASE - WHEN [c].[CustomerID] LIKE N'S%' - THEN 1 ELSE 2 -END, [c].[CustomerID]", - // - @"SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT [c0].[CustomerID], CASE - WHEN [c0].[CustomerID] LIKE N'S%' - THEN 1 ELSE 2 - END AS [c] - FROM [Customers] AS [c0] -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] -ORDER BY [t].[c], [t].[CustomerID]"); + WHEN [c].[CustomerID] LIKE N'S%' THEN 1 + ELSE 2 +END, [c].[CustomerID]"); } public override void Include_reference_distinct_is_server_evaluated(bool useString) @@ -1446,10 +1080,13 @@ public override void Include_reference_distinct_is_server_evaluated(bool useStri base.Include_reference_distinct_is_server_evaluated(useString); AssertSql( - @"SELECT DISTINCT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [o.Customer].[CustomerID], [o.Customer].[Address], [o.Customer].[City], [o.Customer].[CompanyName], [o.Customer].[ContactName], [o.Customer].[ContactTitle], [o.Customer].[Country], [o.Customer].[Fax], [o.Customer].[Phone], [o.Customer].[PostalCode], [o.Customer].[Region] -FROM [Orders] AS [o] -LEFT JOIN [Customers] AS [o.Customer] ON [o].[CustomerID] = [o.Customer].[CustomerID] -WHERE [o].[OrderID] < 10250"); + @"SELECT [t].[OrderID], [t].[CustomerID], [t].[EmployeeID], [t].[OrderDate], [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].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] + FROM [Orders] AS [o] + WHERE [o].[OrderID] < 10250 +) AS [t] +LEFT JOIN [Customers] AS [c] ON [t].[CustomerID] = [c].[CustomerID]"); } public override void Include_collection_distinct_is_server_evaluated(bool useString) @@ -1457,18 +1094,13 @@ public override void Include_collection_distinct_is_server_evaluated(bool useStr base.Include_collection_distinct_is_server_evaluated(useString); AssertSql( - @"SELECT DISTINCT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] -FROM [Customers] AS [c] -WHERE [c].[CustomerID] LIKE N'A%' -ORDER BY [c].[CustomerID]", - // - @"SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT DISTINCT [c0].[CustomerID] - FROM [Customers] AS [c0] - WHERE [c0].[CustomerID] LIKE N'A%' -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] + @"SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] +FROM ( + SELECT DISTINCT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] + FROM [Customers] AS [c] + WHERE [c].[CustomerID] LIKE N'A%' +) AS [t] +LEFT JOIN [Orders] AS [o] ON [t].[CustomerID] = [o].[CustomerID] ORDER BY [t].[CustomerID]"); } @@ -1477,19 +1109,11 @@ public override void Include_collection_OrderBy_object(bool useString) base.Include_collection_OrderBy_object(useString); AssertSql( - @"SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] + @"SELECT [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate], [o0].[OrderID], [o0].[ProductID], [o0].[Discount], [o0].[Quantity], [o0].[UnitPrice] FROM [Orders] AS [o] +LEFT JOIN [Order Details] AS [o0] ON [o].[OrderID] = [o0].[OrderID] WHERE [o].[OrderID] < 10250 -ORDER BY [o].[OrderID]", - // - @"SELECT [o.OrderDetails].[OrderID], [o.OrderDetails].[ProductID], [o.OrderDetails].[Discount], [o.OrderDetails].[Quantity], [o.OrderDetails].[UnitPrice] -FROM [Order Details] AS [o.OrderDetails] -INNER JOIN ( - SELECT [o0].[OrderID] - FROM [Orders] AS [o0] - WHERE [o0].[OrderID] < 10250 -) AS [t] ON [o.OrderDetails].[OrderID] = [t].[OrderID] -ORDER BY [t].[OrderID]"); +ORDER BY [o].[OrderID]"); } public override void Include_collection_OrderBy_empty_list_contains(bool useString) @@ -1553,29 +1177,21 @@ public override void Include_collection_OrderBy_list_contains(bool useString) AssertSql( @"@__p_1='1' -SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] -FROM [Customers] AS [c] -WHERE [c].[CustomerID] LIKE N'A%' -ORDER BY CASE - WHEN [c].[CustomerID] IN (N'ALFKI') - THEN CAST(1 AS bit) ELSE CAST(0 AS bit) -END, [c].[CustomerID] -OFFSET @__p_1 ROWS", - // - @"@__p_1='1' - -SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT [c0].[CustomerID], CASE - WHEN [c0].[CustomerID] IN (N'ALFKI') - THEN CAST(1 AS bit) ELSE CAST(0 AS bit) +SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] +FROM ( + SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region], CASE + WHEN [c].[CustomerID] IN (N'ALFKI') THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) END AS [c] - FROM [Customers] AS [c0] - WHERE [c0].[CustomerID] LIKE N'A%' - ORDER BY [c], [c0].[CustomerID] + FROM [Customers] AS [c] + WHERE [c].[CustomerID] LIKE N'A%' + ORDER BY CASE + WHEN [c].[CustomerID] IN (N'ALFKI') THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END, [c].[CustomerID] OFFSET @__p_1 ROWS -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] +) AS [t] +LEFT JOIN [Orders] AS [o] ON [t].[CustomerID] = [o].[CustomerID] ORDER BY [t].[c], [t].[CustomerID]"); } @@ -1586,38 +1202,26 @@ public override void Include_collection_OrderBy_list_does_not_contains(bool useS AssertSql( @"@__p_1='1' -SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region] -FROM [Customers] AS [c] -WHERE [c].[CustomerID] LIKE N'A%' -ORDER BY CASE - WHEN [c].[CustomerID] NOT IN (N'ALFKI') - THEN CAST(1 AS bit) ELSE CAST(0 AS bit) -END, [c].[CustomerID] -OFFSET @__p_1 ROWS", - // - @"@__p_1='1' - -SELECT [c.Orders].[OrderID], [c.Orders].[CustomerID], [c.Orders].[EmployeeID], [c.Orders].[OrderDate] -FROM [Orders] AS [c.Orders] -INNER JOIN ( - SELECT [c0].[CustomerID], CASE - WHEN [c0].[CustomerID] NOT IN (N'ALFKI') - THEN CAST(1 AS bit) ELSE CAST(0 AS bit) +SELECT [t].[CustomerID], [t].[Address], [t].[City], [t].[CompanyName], [t].[ContactName], [t].[ContactTitle], [t].[Country], [t].[Fax], [t].[Phone], [t].[PostalCode], [t].[Region], [o].[OrderID], [o].[CustomerID], [o].[EmployeeID], [o].[OrderDate] +FROM ( + SELECT [c].[CustomerID], [c].[Address], [c].[City], [c].[CompanyName], [c].[ContactName], [c].[ContactTitle], [c].[Country], [c].[Fax], [c].[Phone], [c].[PostalCode], [c].[Region], CASE + WHEN [c].[CustomerID] NOT IN (N'ALFKI') THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) END AS [c] - FROM [Customers] AS [c0] - WHERE [c0].[CustomerID] LIKE N'A%' - ORDER BY [c], [c0].[CustomerID] + FROM [Customers] AS [c] + WHERE [c].[CustomerID] LIKE N'A%' + ORDER BY CASE + WHEN [c].[CustomerID] NOT IN (N'ALFKI') THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END, [c].[CustomerID] OFFSET @__p_1 ROWS -) AS [t] ON [c.Orders].[CustomerID] = [t].[CustomerID] +) AS [t] +LEFT JOIN [Orders] AS [o] ON [t].[CustomerID] = [o].[CustomerID] ORDER BY [t].[c], [t].[CustomerID]"); } private void AssertSql(params string[] expected) - // issue #15064 - //=> Fixture.TestSqlLoggerFactory.AssertBaseline(expected); - { - return; - } + => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); protected override void ClearLog() => Fixture.TestSqlLoggerFactory.Clear(); diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs index 77a1544ebc7..3b8ae2c1c35 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs @@ -357,7 +357,7 @@ private SqlServerTestStore CreateDatabase603() #region Bugs925_926 - [ConditionalFact(Skip = "issue #15611")] + [ConditionalFact] public void Include_on_entity_with_composite_key_One_To_Many_bugs_925_926() { using (CreateDatabase925()) @@ -372,22 +372,15 @@ public void Include_on_entity_with_composite_key_One_To_Many_bugs_925_926() Assert.Equal(3, result[1].Orders.Count); AssertSql( - @"SELECT [c].[FirstName], [c].[LastName] + @"SELECT [c].[FirstName], [c].[LastName], [o].[Id], [o].[CustomerFirstName], [o].[CustomerLastName], [o].[Name] FROM [Customer] AS [c] -ORDER BY [c].[FirstName], [c].[LastName]", - // - @"SELECT [c.Orders].[Id], [c.Orders].[CustomerFirstName], [c.Orders].[CustomerLastName], [c.Orders].[Name] -FROM [Order] AS [c.Orders] -INNER JOIN ( - SELECT [c0].[FirstName], [c0].[LastName] - FROM [Customer] AS [c0] -) AS [t] ON ([c.Orders].[CustomerFirstName] = [t].[FirstName]) AND ([c.Orders].[CustomerLastName] = [t].[LastName]) -ORDER BY [t].[FirstName], [t].[LastName]"); +LEFT JOIN [Order] AS [o] ON (([c].[FirstName] = [o].[CustomerFirstName]) AND [o].[CustomerFirstName] IS NOT NULL) AND (([c].[LastName] = [o].[CustomerLastName]) AND [o].[CustomerLastName] IS NOT NULL) +ORDER BY [c].[FirstName], [c].[LastName]"); } } } - [ConditionalFact(Skip = "QueryIssue")] + [ConditionalFact] public void Include_on_entity_with_composite_key_Many_To_One_bugs_925_926() { using (CreateDatabase925()) @@ -404,12 +397,10 @@ public void Include_on_entity_with_composite_key_Many_To_One_bugs_925_926() Assert.NotNull(result[3].Customer); Assert.NotNull(result[4].Customer); - var expectedSql = - @"SELECT [o].[Id], [o].[CustomerFirstName], [o].[CustomerLastName], [o].[Name], [o.Customer].[FirstName], [o.Customer].[LastName] + AssertSql( + @"SELECT [o].[Id], [o].[CustomerFirstName], [o].[CustomerLastName], [o].[Name], [c].[FirstName], [c].[LastName] FROM [Order] AS [o] -LEFT JOIN [Customer] AS [o.Customer] ON ([o].[CustomerFirstName] = [o.Customer].[FirstName]) AND ([o].[CustomerLastName] = [o.Customer].[LastName])"; - - AssertSql(expectedSql); +LEFT JOIN [Customer] AS [c] ON (([o].[CustomerFirstName] = [c].[FirstName]) AND [o].[CustomerFirstName] IS NOT NULL) AND (([o].[CustomerLastName] = [c].[LastName]) AND [o].[CustomerLastName] IS NOT NULL)"); } } } @@ -5500,7 +5491,7 @@ public virtual void Union_and_insert_12549() } private SqlServerTestStore CreateDatabase12549() - => CreateTestStore(() => new MyContext12549(_options), context => {}); + => CreateTestStore(() => new MyContext12549(_options), context => { }); public class MyContext12549 : DbContext { @@ -5508,7 +5499,7 @@ public class MyContext12549 : DbContext public DbSet Table2 { get; set; } public MyContext12549(DbContextOptions options) - : base(options) + : base(options) { } } @@ -5525,6 +5516,107 @@ public class Table2_12549 #endregion + #region Bug16233 + + [ConditionalFact] + public virtual void Derived_reference_is_skipped_when_base_type() + { + using (CreateDatabase16233()) + { + using (var context = new MyContext16233(_options)) + { + var result = context.Bases.Include(p => ((DerivedType16233)p).Reference).OrderBy(b => b.Id).ToList(); + + Assert.Equal(3, result.Count); + Assert.NotNull(Assert.IsType(result[1]).Reference); + Assert.Null(Assert.IsType(result[2]).Reference); + Assert.True(context.Entry(Assert.IsType(result[2])).Reference("Reference").IsLoaded); + + AssertSql( + @"SELECT [b].[Id], [b].[Discriminator], [r].[Id], [r].[DerivedTypeId] +FROM [Bases] AS [b] +LEFT JOIN [Reference16233] AS [r] ON [b].[Id] = [r].[DerivedTypeId] +WHERE [b].[Discriminator] IN (N'BaseType16233', N'DerivedType16233') +ORDER BY [b].[Id]"); + } + } + } + + [ConditionalFact] + public virtual void Derived_reference_is_skipped_when_base_type_no_tracking() + { + using (CreateDatabase16233()) + { + using (var context = new MyContext16233(_options)) + { + var result = context.Bases.AsNoTracking().Include(p => ((DerivedType16233)p).Reference).OrderBy(b => b.Id).ToList(); + + Assert.Equal(3, result.Count); + Assert.NotNull(Assert.IsType(result[1]).Reference); + Assert.NotNull(Assert.IsType(result[1]).Reference.DerivedType); + Assert.Null(Assert.IsType(result[2]).Reference); + + AssertSql( + @"SELECT [b].[Id], [b].[Discriminator], [r].[Id], [r].[DerivedTypeId] +FROM [Bases] AS [b] +LEFT JOIN [Reference16233] AS [r] ON [b].[Id] = [r].[DerivedTypeId] +WHERE [b].[Discriminator] IN (N'BaseType16233', N'DerivedType16233') +ORDER BY [b].[Id]"); + } + } + } + + private SqlServerTestStore CreateDatabase16233() + { + return CreateTestStore( + () => new MyContext16233(_options), + context => + { + context.AddRange( + new BaseType16233(), + new DerivedType16233 + { + Reference = new Reference16233() + }, + new DerivedType16233()); + + context.SaveChanges(); + + ClearLog(); + }); + } + + + public class MyContext16233 : DbContext + { + public virtual DbSet Bases { get; set; } + public virtual DbSet Derived { get; set; } + + public MyContext16233(DbContextOptions options) + : base(options) + { + } + } + + public class BaseType16233 + { + public int Id { get; set; } + } + + public class DerivedType16233 : BaseType16233 + { + public Reference16233 Reference { get; set; } + } + + public class Reference16233 + { + public int Id { get; set; } + public int DerivedTypeId { get; set; } + public DerivedType16233 DerivedType { get; set; } + } + + #endregion + private DbContextOptions _options; private SqlServerTestStore CreateTestStore( diff --git a/test/EFCore.SqlServer.FunctionalTests/SqlServerEndToEndTest.cs b/test/EFCore.SqlServer.FunctionalTests/SqlServerEndToEndTest.cs index 481f37c6bc1..b3eca98efcc 100644 --- a/test/EFCore.SqlServer.FunctionalTests/SqlServerEndToEndTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/SqlServerEndToEndTest.cs @@ -691,7 +691,7 @@ public void Adding_an_item_to_a_collection_marks_it_as_modified() } } - [ConditionalFact(Skip = "issue #15992")] + [ConditionalFact] public void Can_set_reference_twice() { using (var testDatabase = SqlServerTestStore.CreateInitialized(DatabaseName)) @@ -740,7 +740,7 @@ public void Can_set_reference_twice() } } - [ConditionalFact(Skip = "issue #15992")] + [ConditionalFact] public void Can_include_on_loaded_entity() { using (var testDatabase = SqlServerTestStore.CreateInitialized(DatabaseName))