diff --git a/src/EFCore.Relational/Extensions/RelationalEntityTypeBuilderExtensions.cs b/src/EFCore.Relational/Extensions/RelationalEntityTypeBuilderExtensions.cs index 74ad32b2bf1..98000b2490b 100644 --- a/src/EFCore.Relational/Extensions/RelationalEntityTypeBuilderExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalEntityTypeBuilderExtensions.cs @@ -51,7 +51,7 @@ public static EntityTypeBuilder ToTable( { Check.NotNull(buildAction, nameof(buildAction)); - buildAction(new TableBuilder(null, null, entityTypeBuilder.Metadata)); + buildAction(new TableBuilder(null, null, entityTypeBuilder)); return entityTypeBuilder; } @@ -76,7 +76,7 @@ public static EntityTypeBuilder ToTable( entityTypeBuilder.Metadata.SetTableName(name); entityTypeBuilder.Metadata.SetSchema(null); - buildAction(new TableBuilder(name, null, entityTypeBuilder.Metadata)); + buildAction(new TableBuilder(name, null, entityTypeBuilder)); return entityTypeBuilder; } @@ -114,7 +114,7 @@ public static EntityTypeBuilder ToTable( { Check.NotNull(buildAction, nameof(buildAction)); - buildAction(new TableBuilder(null, null, entityTypeBuilder.Metadata)); + buildAction(new TableBuilder(null, null, entityTypeBuilder)); return entityTypeBuilder; } @@ -141,7 +141,7 @@ public static EntityTypeBuilder ToTable( entityTypeBuilder.Metadata.SetTableName(name); entityTypeBuilder.Metadata.SetSchema(null); - buildAction(new TableBuilder(name, null, entityTypeBuilder.Metadata)); + buildAction(new TableBuilder(name, null, entityTypeBuilder)); return entityTypeBuilder; } @@ -192,7 +192,7 @@ public static EntityTypeBuilder ToTable( entityTypeBuilder.Metadata.SetTableName(name); entityTypeBuilder.Metadata.SetSchema(schema); - buildAction(new TableBuilder(name, schema, entityTypeBuilder.Metadata)); + buildAction(new TableBuilder(name, schema, entityTypeBuilder)); return entityTypeBuilder; } @@ -240,7 +240,7 @@ public static EntityTypeBuilder ToTable( entityTypeBuilder.Metadata.SetTableName(name); entityTypeBuilder.Metadata.SetSchema(schema); - buildAction(new TableBuilder(name, schema, entityTypeBuilder.Metadata)); + buildAction(new TableBuilder(name, schema, entityTypeBuilder)); return entityTypeBuilder; } @@ -277,11 +277,11 @@ public static OwnedNavigationBuilder ToTable( /// The same builder instance so that multiple calls can be chained. public static OwnedNavigationBuilder ToTable( this OwnedNavigationBuilder referenceOwnershipBuilder, - Action buildAction) + Action buildAction) { Check.NotNull(buildAction, nameof(buildAction)); - buildAction(new TableBuilder(null, null, referenceOwnershipBuilder.OwnedEntityType)); + buildAction(new OwnedNavigationTableBuilder(null, null, referenceOwnershipBuilder)); return referenceOwnershipBuilder; } @@ -297,13 +297,13 @@ public static OwnedNavigationBuilder ToTable( /// The same builder instance so that multiple calls can be chained. public static OwnedNavigationBuilder ToTable( this OwnedNavigationBuilder referenceOwnershipBuilder, - Action> buildAction) + Action> buildAction) where TOwnerEntity : class where TRelatedEntity : class { Check.NotNull(buildAction, nameof(buildAction)); - buildAction(new TableBuilder(null, null, referenceOwnershipBuilder.OwnedEntityType)); + buildAction(new OwnedNavigationTableBuilder(null, null, referenceOwnershipBuilder)); return referenceOwnershipBuilder; } @@ -337,14 +337,14 @@ public static OwnedNavigationBuilder ToTable buildAction) + Action buildAction) { Check.NullButNotEmpty(name, nameof(name)); Check.NotNull(buildAction, nameof(buildAction)); referenceOwnershipBuilder.OwnedEntityType.SetTableName(name); referenceOwnershipBuilder.OwnedEntityType.SetSchema(null); - buildAction(new TableBuilder(name, null, referenceOwnershipBuilder.OwnedEntityType)); + buildAction(new OwnedNavigationTableBuilder(name, null, referenceOwnershipBuilder)); return referenceOwnershipBuilder; } @@ -362,7 +362,7 @@ public static OwnedNavigationBuilder ToTable( public static OwnedNavigationBuilder ToTable( this OwnedNavigationBuilder referenceOwnershipBuilder, string? name, - Action> buildAction) + Action> buildAction) where TOwnerEntity : class where TRelatedEntity : class { @@ -371,7 +371,7 @@ public static OwnedNavigationBuilder ToTable(name, null, referenceOwnershipBuilder.OwnedEntityType)); + buildAction(new OwnedNavigationTableBuilder(name, null, referenceOwnershipBuilder)); return referenceOwnershipBuilder; } @@ -415,7 +415,7 @@ public static OwnedNavigationBuilder ToTable( this OwnedNavigationBuilder referenceOwnershipBuilder, string name, string? schema, - Action buildAction) + Action buildAction) { Check.NotNull(name, nameof(name)); Check.NullButNotEmpty(schema, nameof(schema)); @@ -423,7 +423,7 @@ public static OwnedNavigationBuilder ToTable( referenceOwnershipBuilder.OwnedEntityType.SetTableName(name); referenceOwnershipBuilder.OwnedEntityType.SetSchema(schema); - buildAction(new TableBuilder(name, schema, referenceOwnershipBuilder.OwnedEntityType)); + buildAction(new OwnedNavigationTableBuilder(name, schema, referenceOwnershipBuilder)); return referenceOwnershipBuilder; } @@ -462,7 +462,7 @@ public static OwnedNavigationBuilder ToTable referenceOwnershipBuilder, string name, string? schema, - Action> buildAction) + Action> buildAction) where TOwnerEntity : class where TRelatedEntity : class { @@ -472,7 +472,7 @@ public static OwnedNavigationBuilder ToTable(name, schema, referenceOwnershipBuilder.OwnedEntityType)); + buildAction(new OwnedNavigationTableBuilder(name, schema, referenceOwnershipBuilder)); return referenceOwnershipBuilder; } diff --git a/src/EFCore.Relational/Metadata/Builders/OwnedNavigationTableBuilder.cs b/src/EFCore.Relational/Metadata/Builders/OwnedNavigationTableBuilder.cs new file mode 100644 index 00000000000..1de6874c01c --- /dev/null +++ b/src/EFCore.Relational/Metadata/Builders/OwnedNavigationTableBuilder.cs @@ -0,0 +1,79 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.ComponentModel; + +namespace Microsoft.EntityFrameworkCore.Metadata.Builders; + +/// +/// Instances of this class are returned from methods when using the API +/// and it is not designed to be directly constructed in your application code. +/// +public class OwnedNavigationTableBuilder +{ + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + [EntityFrameworkInternal] + public OwnedNavigationTableBuilder(string? name, string? schema, OwnedNavigationBuilder ownedNavigationBuilder) + { + OwnedNavigationBuilder = ownedNavigationBuilder; + } + + /// + /// The entity type being configured. + /// + public virtual IMutableEntityType Metadata => OwnedNavigationBuilder.OwnedEntityType; + + /// + /// The entity type builder. + /// + public virtual OwnedNavigationBuilder OwnedNavigationBuilder { get; } + + /// + /// Configures the table to be ignored by migrations. + /// + /// + /// See Database migrations for more information. + /// + /// A value indicating whether the table should be managed by migrations. + /// The same builder instance so that multiple calls can be chained. + public virtual OwnedNavigationTableBuilder ExcludeFromMigrations(bool excluded = true) + { + Metadata.SetIsTableExcludedFromMigrations(excluded); + + return this; + } + + #region Hidden System.Object members + + /// + /// Returns a string that represents the current object. + /// + /// A string that represents the current object. + [EditorBrowsable(EditorBrowsableState.Never)] + public override string? ToString() + => base.ToString(); + + /// + /// Determines whether the specified object is equal to the current object. + /// + /// The object to compare with the current object. + /// if the specified object is equal to the current object; otherwise, . + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object? obj) + => base.Equals(obj); + + /// + /// Serves as the default hash function. + /// + /// A hash code for the current object. + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() + => base.GetHashCode(); + + #endregion +} diff --git a/src/EFCore.Relational/Metadata/Builders/OwnedNavigationTableBuilder`.cs b/src/EFCore.Relational/Metadata/Builders/OwnedNavigationTableBuilder`.cs new file mode 100644 index 00000000000..af93328a20f --- /dev/null +++ b/src/EFCore.Relational/Metadata/Builders/OwnedNavigationTableBuilder`.cs @@ -0,0 +1,36 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.EntityFrameworkCore.Metadata.Builders; + +/// +/// Instances of this class are returned from methods when using the API +/// and it is not designed to be directly constructed in your application code. +/// +/// The entity type being configured. +public class OwnedNavigationTableBuilder : OwnedNavigationTableBuilder + where TEntity : class +{ + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + [EntityFrameworkInternal] + public OwnedNavigationTableBuilder(string? name, string? schema, OwnedNavigationBuilder referenceOwnershipBuilder) + : base(name, schema, referenceOwnershipBuilder) + { + } + + /// + /// Configures the table to be ignored by migrations. + /// + /// + /// See Database migrations for more information. + /// + /// A value indicating whether the table should be managed by migrations. + /// The same builder instance so that multiple calls can be chained. + public new virtual OwnedNavigationTableBuilder ExcludeFromMigrations(bool excluded = true) + => (OwnedNavigationTableBuilder)base.ExcludeFromMigrations(excluded); +} diff --git a/src/EFCore.Relational/Metadata/Builders/TableBuilder.cs b/src/EFCore.Relational/Metadata/Builders/TableBuilder.cs index 2ca8d1b9a8a..44e5a43ea66 100644 --- a/src/EFCore.Relational/Metadata/Builders/TableBuilder.cs +++ b/src/EFCore.Relational/Metadata/Builders/TableBuilder.cs @@ -18,15 +18,20 @@ public class TableBuilder /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [EntityFrameworkInternal] - public TableBuilder(string? name, string? schema, IMutableEntityType entityType) + public TableBuilder(string? name, string? schema, EntityTypeBuilder entityTypeBuilder) { - Metadata = entityType; + EntityTypeBuilder = entityTypeBuilder; } /// /// The entity type being configured. /// - public virtual IMutableEntityType Metadata { get; } + public virtual IMutableEntityType Metadata => EntityTypeBuilder.Metadata; + + /// + /// The entity type builder. + /// + public virtual EntityTypeBuilder EntityTypeBuilder { get; } /// /// Configures the table to be ignored by migrations. diff --git a/src/EFCore.Relational/Metadata/Builders/TableBuilder`.cs b/src/EFCore.Relational/Metadata/Builders/TableBuilder`.cs index 3a43e10094b..c02dd30e4f5 100644 --- a/src/EFCore.Relational/Metadata/Builders/TableBuilder`.cs +++ b/src/EFCore.Relational/Metadata/Builders/TableBuilder`.cs @@ -18,8 +18,8 @@ public class TableBuilder : TableBuilder /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [EntityFrameworkInternal] - public TableBuilder(string? name, string? schema, IMutableEntityType entityType) - : base(name, schema, entityType) + public TableBuilder(string? name, string? schema, EntityTypeBuilder entityTypeBuilder) + : base(name, schema, entityTypeBuilder) { } diff --git a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs index 0edde187a9a..66317860dee 100644 --- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs @@ -1080,11 +1080,18 @@ protected override Expression VisitExtension(Expression extensionExpression) return null; } + var entityProjectionExpression = GetEntityProjectionExpression(entityShaperExpression); var foreignKey = navigation.ForeignKey; if (navigation.IsCollection) { - var innerShapedQuery = CreateShapedQueryExpression( - targetEntityType, _sqlExpressionFactory.Select(targetEntityType)); + var innerSelectExpression = BuildInnerSelectExpressionForOwnedTypeMappedToDifferentTable( + entityProjectionExpression, + navigation, + foreignKey, + targetEntityType); + + var innerShapedQuery = CreateShapedQueryExpression( + targetEntityType, innerSelectExpression); var makeNullable = foreignKey.PrincipalKey.Properties .Concat(foreignKey.Properties) @@ -1132,7 +1139,6 @@ outerKey is NewArrayExpression newArrayExpression Expression.Quote(correlationPredicate)); } - var entityProjectionExpression = GetEntityProjectionExpression(entityShaperExpression); var innerShaper = entityProjectionExpression.BindNavigation(navigation); if (innerShaper == null) { @@ -1175,7 +1181,12 @@ outerKey is NewArrayExpression newArrayExpression // Owned types don't support inheritance See https://github.com/dotnet/efcore/issues/9630 // So there is no handling for dependent having TPT table = targetEntityType.GetViewOrTableMappings().Single().Table; - var innerSelectExpression = _sqlExpressionFactory.Select(targetEntityType); + var innerSelectExpression = BuildInnerSelectExpressionForOwnedTypeMappedToDifferentTable( + entityProjectionExpression, + navigation, + foreignKey, + targetEntityType); + var innerShapedQuery = CreateShapedQueryExpression(targetEntityType, innerSelectExpression); var makeNullable = foreignKey.PrincipalKey.Properties @@ -1231,6 +1242,51 @@ outerKey is NewArrayExpression newArrayExpression targetEntityType, (ProjectionBindingExpression)entityShaperExpression.ValueBufferExpression, navigation); + + SelectExpression BuildInnerSelectExpressionForOwnedTypeMappedToDifferentTable( + EntityProjectionExpression entityProjectionExpression, + INavigation navigation, + IForeignKey foreignKey, + IEntityType targetEntityType) + { + // just need any column - we use it only to extract the table it originated from + var sourceColumn = entityProjectionExpression + .BindProperty( + navigation.IsOnDependent + ? foreignKey.Properties[0] + : foreignKey.PrincipalKey.Properties[0]); + + var sourceTable = FindRootTableExpressionForColumn(sourceColumn.Table, sourceColumn.Name); + var ownedTable = new TableExpression(targetEntityType.GetTableMappings().Single().Table); + + foreach (var annotation in sourceTable.GetAnnotations()) + { + ownedTable.SetAnnotation(annotation.Name, annotation.Value); + } + + return _sqlExpressionFactory.Select(targetEntityType, ownedTable); + } + + static TableExpressionBase FindRootTableExpressionForColumn(TableExpressionBase table, string columnName) + { + if (table is JoinExpressionBase joinExpressionBase) + { + table = joinExpressionBase.Table; + } + else if (table is SetOperationBase setOperationBase) + { + table = setOperationBase.Source1; + } + + if (table is SelectExpression selectExpression) + { + var matchingProjection = (ColumnExpression)selectExpression.Projection.Where(p => p.Alias == columnName).Single().Expression; + + return FindRootTableExpressionForColumn(matchingProjection.Table, matchingProjection.Name); + } + + return table; + } } private static Expression AddConvertToObject(Expression expression) diff --git a/src/EFCore.Relational/Query/SqlExpressions/CrossApplyExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/CrossApplyExpression.cs index bbaf516a4a1..bfda428e658 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/CrossApplyExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/CrossApplyExpression.cs @@ -19,7 +19,12 @@ public class CrossApplyExpression : JoinExpressionBase /// /// A table source to CROSS APPLY with. public CrossApplyExpression(TableExpressionBase table) - : base(table) + : this(table, annotations: null) + { + } + + private CrossApplyExpression(TableExpressionBase table, IEnumerable? annotations) + : base(table, annotations) { } diff --git a/src/EFCore.Relational/Query/SqlExpressions/ExceptExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/ExceptExpression.cs index 06b62546cca..5862e40f4ce 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/ExceptExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/ExceptExpression.cs @@ -26,7 +26,17 @@ public ExceptExpression( SelectExpression source1, SelectExpression source2, bool distinct) - : base(alias, source1, source2, distinct) + : this(alias, source1, source2, distinct, annotations: null) + { + } + + private ExceptExpression( + string alias, + SelectExpression source1, + SelectExpression source2, + bool distinct, + IEnumerable? annotations) + : base(alias, source1, source2, distinct, annotations) { } @@ -48,7 +58,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// This expression if no children changed, or an expression with the updated children. public virtual ExceptExpression Update(SelectExpression source1, SelectExpression source2) => source1 != Source1 || source2 != Source2 - ? new ExceptExpression(Alias, source1, source2, IsDistinct) + ? new ExceptExpression(Alias, source1, source2, IsDistinct, GetAnnotations()) : this; /// diff --git a/src/EFCore.Relational/Query/SqlExpressions/FromSqlExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/FromSqlExpression.cs index 9a3bc027466..f5a1e0a0daf 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/FromSqlExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/FromSqlExpression.cs @@ -23,7 +23,18 @@ public class FromSqlExpression : TableExpressionBase, IClonableTableExpressionBa /// A user-provided custom SQL for the table source. /// A user-provided parameters to pass to the custom SQL. public FromSqlExpression(string alias, string sql, Expression arguments) - : base(alias) + : this(alias, sql, arguments, annotations: null) + { + Sql = sql; + Arguments = arguments; + } + + private FromSqlExpression( + string alias, + string sql, + Expression arguments, + IEnumerable? annotations) + : base(alias, annotations) { Sql = sql; Arguments = arguments; @@ -66,7 +77,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// public virtual TableExpressionBase Clone() - => new FromSqlExpression(Alias, Sql, Arguments); + => new FromSqlExpression(Alias, Sql, Arguments, GetAnnotations()); /// protected override void Print(ExpressionPrinter expressionPrinter) diff --git a/src/EFCore.Relational/Query/SqlExpressions/InnerJoinExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/InnerJoinExpression.cs index b1c3eca9920..feb7f87e1b4 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/InnerJoinExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/InnerJoinExpression.cs @@ -20,7 +20,15 @@ public class InnerJoinExpression : PredicateJoinExpressionBase /// A table source to INNER JOIN with. /// A predicate to use for the join. public InnerJoinExpression(TableExpressionBase table, SqlExpression joinPredicate) - : base(table, joinPredicate) + : this(table, joinPredicate, annotations: null) + { + } + + private InnerJoinExpression( + TableExpressionBase table, + SqlExpression joinPredicate, + IEnumerable? annotations) + : base(table, joinPredicate, annotations) { } diff --git a/src/EFCore.Relational/Query/SqlExpressions/IntersectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/IntersectExpression.cs index cdf006597fb..3ad33b93832 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/IntersectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/IntersectExpression.cs @@ -26,7 +26,17 @@ public IntersectExpression( SelectExpression source1, SelectExpression source2, bool distinct) - : base(alias, source1, source2, distinct) + : this(alias, source1, source2, distinct, annotations: null) + { + } + + private IntersectExpression( + string alias, + SelectExpression source1, + SelectExpression source2, + bool distinct, + IEnumerable? annotations) + : base(alias, source1, source2, distinct, annotations) { } @@ -48,7 +58,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// This expression if no children changed, or an expression with the updated children. public virtual IntersectExpression Update(SelectExpression source1, SelectExpression source2) => source1 != Source1 || source2 != Source2 - ? new IntersectExpression(Alias, source1, source2, IsDistinct) + ? new IntersectExpression(Alias, source1, source2, IsDistinct, GetAnnotations()) : this; /// diff --git a/src/EFCore.Relational/Query/SqlExpressions/JoinExpressionBase.cs b/src/EFCore.Relational/Query/SqlExpressions/JoinExpressionBase.cs index 0a1f349954e..7e5653e041f 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/JoinExpressionBase.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/JoinExpressionBase.cs @@ -19,7 +19,17 @@ public abstract class JoinExpressionBase : TableExpressionBase /// /// A table source to join with. protected JoinExpressionBase(TableExpressionBase table) - : base(null) + : this(table, annotations: null) + { + } + + /// + /// Creates a new instance of the class. + /// + /// A table source to join with. + /// A collection of annotations associated with this expression. + protected JoinExpressionBase(TableExpressionBase table, IEnumerable? annotations) + : base(alias: null, annotations) { Table = table; } diff --git a/src/EFCore.Relational/Query/SqlExpressions/LeftJoinExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/LeftJoinExpression.cs index fc2d6165c7e..257755fa936 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/LeftJoinExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/LeftJoinExpression.cs @@ -20,7 +20,15 @@ public class LeftJoinExpression : PredicateJoinExpressionBase /// A table source to LEFT JOIN with. /// A predicate to use for the join. public LeftJoinExpression(TableExpressionBase table, SqlExpression joinPredicate) - : base(table, joinPredicate) + : this(table, joinPredicate, annotations: null) + { + } + + private LeftJoinExpression( + TableExpressionBase table, + SqlExpression joinPredicate, + IEnumerable? annotations) + : base(table, joinPredicate, annotations) { } diff --git a/src/EFCore.Relational/Query/SqlExpressions/OuterApplyExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/OuterApplyExpression.cs index 4254beb8f82..abfdb7ce048 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/OuterApplyExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/OuterApplyExpression.cs @@ -19,7 +19,12 @@ public class OuterApplyExpression : JoinExpressionBase /// /// A table source to OUTER APPLY with. public OuterApplyExpression(TableExpressionBase table) - : base(table) + : this(table, annotations: null) + { + } + + private OuterApplyExpression(TableExpressionBase table, IEnumerable? annotations) + : base(table, annotations) { } diff --git a/src/EFCore.Relational/Query/SqlExpressions/PredicateJoinExpressionBase.cs b/src/EFCore.Relational/Query/SqlExpressions/PredicateJoinExpressionBase.cs index d575beb8277..8c40d3043a0 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/PredicateJoinExpressionBase.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/PredicateJoinExpressionBase.cs @@ -20,7 +20,21 @@ public abstract class PredicateJoinExpressionBase : JoinExpressionBase /// A table source to join with. /// A predicate to use for the join. protected PredicateJoinExpressionBase(TableExpressionBase table, SqlExpression joinPredicate) - : base(table) + : this(table, joinPredicate, annotations: null) + { + } + + /// + /// Creates a new instance of the class. + /// + /// A table source to join with. + /// A predicate to use for the join. + /// A collection of annotations associated with this expression. + protected PredicateJoinExpressionBase( + TableExpressionBase table, + SqlExpression joinPredicate, + IEnumerable? annotations) + : base(table, annotations) { JoinPredicate = joinPredicate; } diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.Helper.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.Helper.cs index 61da2ed0229..75ad64ab02a 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.Helper.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.Helper.cs @@ -764,7 +764,7 @@ private sealed class CloningExpressionVisitor : ExpressionVisitor var limit = (SqlExpression?)Visit(selectExpression.Limit); var newSelectExpression = new SelectExpression( - selectExpression.Alias, newProjections, newTables, newTableReferences, newGroupBy, newOrderings) + selectExpression.Alias, newProjections, newTables, newTableReferences, newGroupBy, newOrderings, selectExpression.GetAnnotations()) { Predicate = predicate, Having = havingExpression, diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs index ef86be75a21..f3dcc39b2b4 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs @@ -59,8 +59,9 @@ private SelectExpression( List tables, List tableReferences, List groupBy, - List orderings) - : base(alias) + List orderings, + IEnumerable annotations) + : base(alias, annotations) { _projection = projections; _tables = tables; @@ -1429,7 +1430,7 @@ private void ApplySetOperation(SetOperationType setOperationType, SelectExpressi { // TODO: Introduce clone method? See issue#24460 var select1 = new SelectExpression( - null, new List(), _tables.ToList(), _tableReferences.ToList(), _groupBy.ToList(), _orderings.ToList()) + null, new List(), _tables.ToList(), _tableReferences.ToList(), _groupBy.ToList(), _orderings.ToList(), GetAnnotations()) { IsDistinct = IsDistinct, Predicate = Predicate, @@ -1727,7 +1728,8 @@ public void ApplyDefaultIfEmpty(ISqlExpressionFactory sqlExpressionFactory) new List(), new List(), new List(), - new List()); + new List(), + Enumerable.Empty()); if (Orderings.Any() || Limit != null @@ -2580,7 +2582,7 @@ private SqlRemappingVisitor PushdownIntoSubqueryInternal() var subqueryAlias = GenerateUniqueAlias(_usedAliases, "t"); var subquery = new SelectExpression( subqueryAlias, new List(), _tables.ToList(), _tableReferences.ToList(), _groupBy.ToList(), - _orderings.ToList()) + _orderings.ToList(), GetAnnotations()) { IsDistinct = IsDistinct, Predicate = Predicate, @@ -3221,7 +3223,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) { var newTableReferences = _tableReferences.ToList(); var newSelectExpression = new SelectExpression( - Alias, newProjections, newTables, newTableReferences, newGroupBy, newOrderings) + Alias, newProjections, newTables, newTableReferences, newGroupBy, newOrderings, GetAnnotations()) { _clientProjections = _clientProjections, _projectionMapping = _projectionMapping, @@ -3330,7 +3332,7 @@ public SelectExpression Update( var newTableReferences = _tableReferences.ToList(); var newSelectExpression = new SelectExpression( - Alias, projections.ToList(), tables.ToList(), newTableReferences, groupBy.ToList(), orderings.ToList()) + Alias, projections.ToList(), tables.ToList(), newTableReferences, groupBy.ToList(), orderings.ToList(), GetAnnotations()) { _projectionMapping = projectionMapping, _clientProjections = _clientProjections.ToList(), diff --git a/src/EFCore.Relational/Query/SqlExpressions/SetOperationBase.cs b/src/EFCore.Relational/Query/SqlExpressions/SetOperationBase.cs index 7bf4c27b526..370519f245b 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SetOperationBase.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SetOperationBase.cs @@ -28,7 +28,25 @@ protected SetOperationBase( SelectExpression source1, SelectExpression source2, bool distinct) - : base(alias) + : this(alias, source1, source2, distinct, annotations: null) + { + } + + /// + /// Creates a new instance of the class. + /// + /// A string alias for the table source. + /// A table source which is first source in the set operation. + /// A table source which is second source in the set operation. + /// A bool value indicating whether result will remove duplicate rows. + /// Collection of annotations associated with this expression. + protected SetOperationBase( + string alias, + SelectExpression source1, + SelectExpression source2, + bool distinct, + IEnumerable? annotations) + : base(alias, annotations) { IsDistinct = distinct; Source1 = source1; diff --git a/src/EFCore.Relational/Query/SqlExpressions/TableExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/TableExpression.cs index 3b871e293ae..2e4ed122802 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/TableExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/TableExpression.cs @@ -16,7 +16,12 @@ namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions; public sealed class TableExpression : TableExpressionBase, IClonableTableExpressionBase { internal TableExpression(ITableBase table) - : base(table.Name.Substring(0, 1).ToLowerInvariant()) + : this(table, annotations: null) + { + } + + private TableExpression(ITableBase table, IEnumerable? annotations) + : base(alias: table.Name.Substring(0, 1).ToLowerInvariant(), annotations) { Name = table.Name; Schema = table.Schema; @@ -31,7 +36,16 @@ protected override void Print(ExpressionPrinter expressionPrinter) expressionPrinter.Append(Schema).Append("."); } - expressionPrinter.Append(Name).Append(" AS ").Append(Alias); + expressionPrinter.Append(Name); + var annotations = GetAnnotations(); + if (annotations.Any()) + { + expressionPrinter.Append("["); + expressionPrinter.Append(annotations.Select(a => a.Name + "=" + a.Value).Join(" | ")); + expressionPrinter.Append("]"); + } + + expressionPrinter.Append(" AS ").Append(Alias); } /// @@ -61,7 +75,7 @@ public override string? Alias /// public TableExpressionBase Clone() - => new TableExpression(Table) { Alias = Alias }; + => new TableExpression(Table, GetAnnotations()) { Alias = Alias }; /// public override bool Equals(object? obj) diff --git a/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs b/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs index 2490984ddfd..eac1b7da130 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/TableExpressionBase.cs @@ -12,15 +12,36 @@ namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions; /// not used in application code. /// /// -public abstract class TableExpressionBase : Expression, IPrintableExpression +public abstract class TableExpressionBase : Expression, IPrintableExpression, IMutableAnnotatable { + private SortedDictionary? _annotations; + /// /// Creates a new instance of the class. /// /// A string alias for the table source. protected TableExpressionBase(string? alias) + : this(alias, annotations: null) + { + Alias = alias; + } + + /// + /// Creates a new instance of the class. + /// + /// A string alias for the table source. + /// A collection of annotations associated with this expression. + protected TableExpressionBase(string? alias, IEnumerable? annotations) { Alias = alias; + + if (annotations != null) + { + foreach (var annotation in annotations) + { + SetAnnotation(annotation.Name, annotation.Value); + } + } } /// @@ -40,6 +61,33 @@ public override Type Type public sealed override ExpressionType NodeType => ExpressionType.Extension; + /// + /// Gets the value annotation with the given name, returning if it does not exist. + /// + /// The key of the annotation to find. + /// + /// The value of the existing annotation if an annotation with the specified name already exists. + /// Otherwise, . + /// + public virtual object? this[string name] + { + get => FindAnnotation(name)?.Value; + + set + { + Check.NotEmpty(name, nameof(name)); + + if (value == null) + { + RemoveAnnotation(name); + } + else + { + SetAnnotation(name, value); + } + } + } + /// /// Creates a printable string representation of the given expression using . /// @@ -63,4 +111,135 @@ private bool Equals(TableExpressionBase tableExpressionBase) /// public override int GetHashCode() => HashCode.Combine(Alias); + + /// + /// Adds an annotation to this object. Throws if an annotation with the specified name already exists. + /// + /// The key of the annotation to be added. + /// The value to be stored in the annotation. + /// The newly added annotation. + public virtual Annotation AddAnnotation(string name, object? value) + => AddAnnotation(name, new(name, value)); + + /// + /// Adds an annotation to this object. Throws if an annotation with the specified name already exists. + /// + /// The key of the annotation to be added. + /// The annotation to be added. + /// The added annotation. + protected virtual Annotation AddAnnotation(string name, Annotation annotation) + { + if (FindAnnotation(name) != null) + { + throw new InvalidOperationException(CoreStrings.DuplicateAnnotation(name, ToString())); + } + + SetAnnotation(name, annotation, oldAnnotation: null); + + return annotation; + } + + /// + /// Sets the annotation stored under the given key. Overwrites the existing annotation if an + /// annotation with the specified name already exists. + /// + /// The key of the annotation to be added. + /// The value to be stored in the annotation. + public virtual void SetAnnotation(string name, object? value) + { + var oldAnnotation = FindAnnotation(name); + if (oldAnnotation != null + && Equals(oldAnnotation.Value, value)) + { + return; + } + + SetAnnotation(name, new(name, value), oldAnnotation); + } + + /// + /// Sets the annotation stored under the given key. Overwrites the existing annotation if an + /// annotation with the specified name already exists. + /// + /// The key of the annotation to be added. + /// The annotation to be set. + /// The annotation being replaced. + /// The annotation that was set. + protected virtual Annotation? SetAnnotation( + string name, + Annotation annotation, + Annotation? oldAnnotation) + { + _annotations ??= new SortedDictionary(StringComparer.Ordinal); + _annotations[name] = annotation; + + return annotation; + } + + /// + /// Removes the given annotation from this object. + /// + /// The annotation to remove. + /// The annotation that was removed. + public virtual Annotation? RemoveAnnotation(string name) + { + var annotation = FindAnnotation(name); + if (annotation == null) + { + return null; + } + + _annotations!.Remove(name); + + if (_annotations.Count == 0) + { + _annotations = null; + } + + return annotation; + } + + /// + /// Gets the annotation with the given name, returning if it does not exist. + /// + /// The key of the annotation to find. + /// + /// The existing annotation if an annotation with the specified name already exists. Otherwise, . + /// + public virtual Annotation? FindAnnotation(string name) + { + Check.NotEmpty(name, nameof(name)); + + return _annotations == null + ? null + : _annotations.TryGetValue(name, out var annotation) + ? annotation + : null; + } + + /// + /// Gets all annotations on the current object. + /// + public IEnumerable GetAnnotations() + => _annotations?.Values ?? Enumerable.Empty(); + + /// + [DebuggerStepThrough] + IAnnotation IMutableAnnotatable.AddAnnotation(string name, object? value) + => AddAnnotation(name, value); + + /// + [DebuggerStepThrough] + IAnnotation? IMutableAnnotatable.RemoveAnnotation(string name) + => RemoveAnnotation(name); + + /// + [DebuggerStepThrough] + void IMutableAnnotatable.SetOrRemoveAnnotation(string name, object? value) + => this[name] = value; + + /// + [DebuggerStepThrough] + IAnnotation? IReadOnlyAnnotatable.FindAnnotation(string name) + => FindAnnotation(name); } diff --git a/src/EFCore.Relational/Query/SqlExpressions/UnionExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/UnionExpression.cs index 379eb7da0ad..42f9b9a4bf8 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/UnionExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/UnionExpression.cs @@ -26,7 +26,17 @@ public UnionExpression( SelectExpression source1, SelectExpression source2, bool distinct) - : base(alias, source1, source2, distinct) + : this(alias, source1, source2, distinct, annotations: null) + { + } + + private UnionExpression( + string alias, + SelectExpression source1, + SelectExpression source2, + bool distinct, + IEnumerable? annotations) + : base(alias, source1, source2, distinct, annotations) { } @@ -48,7 +58,7 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// This expression if no children changed, or an expression with the updated children. public virtual UnionExpression Update(SelectExpression source1, SelectExpression source2) => source1 != Source1 || source2 != Source2 - ? new UnionExpression(Alias, source1, source2, IsDistinct) + ? new UnionExpression(Alias, source1, source2, IsDistinct, GetAnnotations()) : this; /// diff --git a/src/EFCore.SqlServer/Extensions/SqlServerTableBuilderExtensions.cs b/src/EFCore.SqlServer/Extensions/SqlServerTableBuilderExtensions.cs index 78ce7315e86..3afdd1ccf4a 100644 --- a/src/EFCore.SqlServer/Extensions/SqlServerTableBuilderExtensions.cs +++ b/src/EFCore.SqlServer/Extensions/SqlServerTableBuilderExtensions.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. - - // ReSharper disable once CheckNamespace namespace Microsoft.EntityFrameworkCore; @@ -27,7 +25,7 @@ public static TemporalTableBuilder IsTemporal( { tableBuilder.Metadata.SetIsTemporal(temporal); - return new TemporalTableBuilder(tableBuilder.Metadata); + return new TemporalTableBuilder(tableBuilder.EntityTypeBuilder); } /// @@ -46,7 +44,7 @@ public static TableBuilder IsTemporal( { tableBuilder.Metadata.SetIsTemporal(true); - buildAction(new TemporalTableBuilder(tableBuilder.Metadata)); + buildAction(new TemporalTableBuilder(tableBuilder.EntityTypeBuilder)); return tableBuilder; } @@ -69,7 +67,7 @@ public static TemporalTableBuilder IsTemporal( { tableBuilder.Metadata.SetIsTemporal(temporal); - return new TemporalTableBuilder(tableBuilder.Metadata); + return new TemporalTableBuilder(tableBuilder.EntityTypeBuilder); } /// @@ -89,7 +87,90 @@ public static TableBuilder IsTemporal( where TEntity : class { tableBuilder.Metadata.SetIsTemporal(true); - buildAction(new TemporalTableBuilder(tableBuilder.Metadata)); + buildAction(new TemporalTableBuilder(tableBuilder.EntityTypeBuilder)); + + return tableBuilder; + } + + /// + /// Configures the table as temporal. + /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// + /// The builder for the table being configured. + /// A value indicating whether the table is temporal. + /// An object that can be used to configure the temporal table. + public static OwnedNavigationTemporalTableBuilder IsTemporal( + this OwnedNavigationTableBuilder tableBuilder, + bool temporal = true) + { + tableBuilder.Metadata.SetIsTemporal(temporal); + + return new OwnedNavigationTemporalTableBuilder(tableBuilder.OwnedNavigationBuilder); + } + + /// + /// Configures the table as temporal. + /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// + /// The builder for the table being configured. + /// An action that performs configuration of the temporal table. + /// The same builder instance so that multiple calls can be chained. + public static OwnedNavigationTableBuilder IsTemporal( + this OwnedNavigationTableBuilder tableBuilder, + Action buildAction) + { + tableBuilder.Metadata.SetIsTemporal(true); + + buildAction(new OwnedNavigationTemporalTableBuilder(tableBuilder.OwnedNavigationBuilder)); + + return tableBuilder; + } + + /// + /// Configures the table as temporal. + /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// + /// The entity type being configured. + /// The builder for the table being configured. + /// A value indicating whether the table is temporal. + /// An object that can be used to configure the temporal table. + public static OwnedNavigationTemporalTableBuilder IsTemporal( + this OwnedNavigationTableBuilder tableBuilder, + bool temporal = true) + where TEntity : class + { + tableBuilder.Metadata.SetIsTemporal(temporal); + + return new OwnedNavigationTemporalTableBuilder(tableBuilder.OwnedNavigationBuilder); + } + + /// + /// Configures the table as temporal. + /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// + /// The entity type being configured. + /// The builder for the table being configured. + /// An action that performs configuration of the temporal table. + /// The same builder instance so that multiple calls can be chained. + public static OwnedNavigationTableBuilder IsTemporal( + this OwnedNavigationTableBuilder tableBuilder, + Action> buildAction) + where TEntity : class + { + tableBuilder.Metadata.SetIsTemporal(true); + buildAction(new OwnedNavigationTemporalTableBuilder(tableBuilder.OwnedNavigationBuilder)); return tableBuilder; } diff --git a/src/EFCore.SqlServer/Infrastructure/Internal/SqlServerModelValidator.cs b/src/EFCore.SqlServer/Infrastructure/Internal/SqlServerModelValidator.cs index 0d8746c853e..86d6b74895d 100644 --- a/src/EFCore.SqlServer/Infrastructure/Internal/SqlServerModelValidator.cs +++ b/src/EFCore.SqlServer/Infrastructure/Internal/SqlServerModelValidator.cs @@ -335,7 +335,60 @@ protected override void ValidateSharedTableCompatibility( if (mappedTypes.Any(t => t.IsTemporal()) && mappedTypes.Select(t => t.GetRootType()).Distinct().Count() > 1) { - throw new InvalidOperationException(SqlServerStrings.TemporalNotSupportedForTableSplitting(tableName)); + // table splitting is only supported when all entites mapped to this table + // have consistent temporal period mappings also + var expectedPeriodStartColumnName = default(string); + var expectedPeriodEndColumnName = default(string); + + foreach (var mappedType in mappedTypes.Where(t => t.BaseType == null)) + { + if (!mappedType.IsTemporal()) + { + throw new InvalidOperationException( + SqlServerStrings.TemporalAllEntitiesMappedToSameTableMustBeTemporal( + mappedType.DisplayName())); + } + + var periodStartPropertyName = mappedType.GetPeriodStartPropertyName(); + var periodEndPropertyName = mappedType.GetPeriodEndPropertyName(); + + var periodStartProperty = mappedType.GetProperty(periodStartPropertyName!); + var periodEndProperty = mappedType.GetProperty(periodEndPropertyName!); + + var storeObjectIdentifier = StoreObjectIdentifier.Table(tableName, mappedType.GetSchema()); + var periodStartColumnName = periodStartProperty.GetColumnName(storeObjectIdentifier); + var periodEndColumnName = periodEndProperty.GetColumnName(storeObjectIdentifier); + + if (expectedPeriodStartColumnName == null) + { + expectedPeriodStartColumnName = periodStartColumnName; + } + else if (expectedPeriodStartColumnName != periodStartColumnName) + { + throw new InvalidOperationException( + SqlServerStrings.TemporalNotSupportedForTableSplittingWithInconsistentPeriodMapping( + "start", + mappedType.DisplayName(), + periodStartPropertyName, + periodStartColumnName, + expectedPeriodStartColumnName)); + } + + if (expectedPeriodEndColumnName == null) + { + expectedPeriodEndColumnName = periodEndColumnName; + } + else if (expectedPeriodEndColumnName != periodEndColumnName) + { + throw new InvalidOperationException( + SqlServerStrings.TemporalNotSupportedForTableSplittingWithInconsistentPeriodMapping( + "end", + mappedType.DisplayName(), + periodEndPropertyName, + periodEndColumnName, + expectedPeriodEndColumnName)); + } + } } base.ValidateSharedTableCompatibility(mappedTypes, tableName, schema, logger); diff --git a/src/EFCore.SqlServer/Metadata/Builders/OwnedNavigationTemporalPeriodPropertyBuilder.cs b/src/EFCore.SqlServer/Metadata/Builders/OwnedNavigationTemporalPeriodPropertyBuilder.cs new file mode 100644 index 00000000000..f5d00215dae --- /dev/null +++ b/src/EFCore.SqlServer/Metadata/Builders/OwnedNavigationTemporalPeriodPropertyBuilder.cs @@ -0,0 +1,73 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.ComponentModel; + +namespace Microsoft.EntityFrameworkCore.Metadata.Builders; + +/// +/// Instances of this class are returned from methods when using the API +/// and it is not designed to be directly constructed in your application code. +/// +public class OwnedNavigationTemporalPeriodPropertyBuilder +{ + private readonly PropertyBuilder _periodPropertyBuilder; + + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + [EntityFrameworkInternal] + public OwnedNavigationTemporalPeriodPropertyBuilder( + PropertyBuilder periodPropertyBuilder) + { + _periodPropertyBuilder = periodPropertyBuilder; + } + + /// + /// Configures the column name the period property maps to. + /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// + /// The name of the column. + /// The same builder instance so that multiple calls can be chained. + public virtual OwnedNavigationTemporalPeriodPropertyBuilder HasColumnName(string name) + { + _periodPropertyBuilder.HasColumnName(name); + + return this; + } + + #region Hidden System.Object members + + /// + /// Returns a string that represents the current object. + /// + /// A string that represents the current object. + [EditorBrowsable(EditorBrowsableState.Never)] + public override string? ToString() + => base.ToString(); + + /// + /// Determines whether the specified object is equal to the current object. + /// + /// The object to compare with the current object. + /// if the specified object is equal to the current object; otherwise, . + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object? obj) + => base.Equals(obj); + + /// + /// Serves as the default hash function. + /// + /// A hash code for the current object. + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() + => base.GetHashCode(); + + #endregion +} diff --git a/src/EFCore.SqlServer/Metadata/Builders/OwnedNavigationTemporalTableBuilder.cs b/src/EFCore.SqlServer/Metadata/Builders/OwnedNavigationTemporalTableBuilder.cs new file mode 100644 index 00000000000..91a9ccf35e0 --- /dev/null +++ b/src/EFCore.SqlServer/Metadata/Builders/OwnedNavigationTemporalTableBuilder.cs @@ -0,0 +1,132 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.ComponentModel; + +namespace Microsoft.EntityFrameworkCore.Metadata.Builders; + +/// +/// Instances of this class are returned from methods when using the API +/// and it is not designed to be directly constructed in your application code. +/// +public class OwnedNavigationTemporalTableBuilder +{ + private readonly OwnedNavigationBuilder _referenceOwnershipBuilder; + + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + [EntityFrameworkInternal] + public OwnedNavigationTemporalTableBuilder(OwnedNavigationBuilder referenceOwnershipBuilder) + { + _referenceOwnershipBuilder = referenceOwnershipBuilder; + } + + /// + /// Configures a history table for the entity mapped to a temporal table. + /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// + /// The name of the history table. + /// The same builder instance so that multiple calls can be chained. + public virtual OwnedNavigationTemporalTableBuilder UseHistoryTable(string name) + { + _referenceOwnershipBuilder.OwnedEntityType.SetHistoryTableName(name); + + return this; + } + + /// + /// Configures a history table for the entity mapped to a temporal table. + /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// + /// The name of the history table. + /// The schema of the history table. + /// The same builder instance so that multiple calls can be chained. + public virtual OwnedNavigationTemporalTableBuilder UseHistoryTable(string name, string? schema) + { + _referenceOwnershipBuilder.OwnedEntityType.SetHistoryTableName(name); + _referenceOwnershipBuilder.OwnedEntityType.SetHistoryTableSchema(schema); + + return this; + } + + /// + /// Returns an object that can be used to configure a period start property of the entity type mapped to a temporal table. + /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// + /// The name of the period start property. + /// An object that can be used to configure the period start property. + public virtual OwnedNavigationTemporalPeriodPropertyBuilder HasPeriodStart(string propertyName) + { + _referenceOwnershipBuilder.OwnedEntityType.SetPeriodStartPropertyName(propertyName); + var propertyBuilder = ConfigurePeriodProperty(propertyName); + + return new OwnedNavigationTemporalPeriodPropertyBuilder(propertyBuilder); + } + + /// + /// Returns an object that can be used to configure a period end property of the entity type mapped to a temporal table. + /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// + /// The name of the period end property. + /// An object that can be used to configure the period end property. + public virtual OwnedNavigationTemporalPeriodPropertyBuilder HasPeriodEnd(string propertyName) + { + _referenceOwnershipBuilder.OwnedEntityType.SetPeriodEndPropertyName(propertyName); + var propertyBuilder = ConfigurePeriodProperty(propertyName); + + return new OwnedNavigationTemporalPeriodPropertyBuilder(propertyBuilder); + } + + private PropertyBuilder ConfigurePeriodProperty(string propertyName) + { + var propertyBuilder = _referenceOwnershipBuilder.Property(typeof(DateTime), propertyName, setTypeConfigurationSource: false); + propertyBuilder.ValueGeneratedOnAddOrUpdate(); + + return propertyBuilder; + } + + #region Hidden System.Object members + + /// + /// Returns a string that represents the current object. + /// + /// A string that represents the current object. + [EditorBrowsable(EditorBrowsableState.Never)] + public override string? ToString() + => base.ToString(); + + /// + /// Determines whether the specified object is equal to the current object. + /// + /// The object to compare with the current object. + /// if the specified object is equal to the current object; otherwise, . + [EditorBrowsable(EditorBrowsableState.Never)] + public override bool Equals(object? obj) + => base.Equals(obj); + + /// + /// Serves as the default hash function. + /// + /// A hash code for the current object. + [EditorBrowsable(EditorBrowsableState.Never)] + public override int GetHashCode() + => base.GetHashCode(); + + #endregion +} diff --git a/src/EFCore.SqlServer/Metadata/Builders/OwnedNavigationTemporalTableBuilder`.cs b/src/EFCore.SqlServer/Metadata/Builders/OwnedNavigationTemporalTableBuilder`.cs new file mode 100644 index 00000000000..c5ae7530334 --- /dev/null +++ b/src/EFCore.SqlServer/Metadata/Builders/OwnedNavigationTemporalTableBuilder`.cs @@ -0,0 +1,38 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.EntityFrameworkCore.Metadata.Builders; + +/// +/// Instances of this class are returned from methods when using the API +/// and it is not designed to be directly constructed in your application code. +/// +/// The entity type being configured. +public class OwnedNavigationTemporalTableBuilder : OwnedNavigationTemporalTableBuilder + where TEntity : class +{ + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + [EntityFrameworkInternal] + public OwnedNavigationTemporalTableBuilder(OwnedNavigationBuilder referenceOwnershipBuilder) + : base(referenceOwnershipBuilder) + { + } + + /// + /// Configures a history table for the entity mapped to a temporal table. + /// + /// + /// See Using SQL Server temporal tables with EF Core + /// for more information. + /// + /// The name of the history table. + /// The schema of the history table. + /// The same builder instance so that multiple calls can be chained. + public new virtual OwnedNavigationTemporalTableBuilder UseHistoryTable(string name, string? schema = null) + => (OwnedNavigationTemporalTableBuilder)base.UseHistoryTable(name, schema); +} diff --git a/src/EFCore.SqlServer/Metadata/Builders/TemporalPeriodPropertyBuilder.cs b/src/EFCore.SqlServer/Metadata/Builders/TemporalPeriodPropertyBuilder.cs index 73444517599..14a7937173d 100644 --- a/src/EFCore.SqlServer/Metadata/Builders/TemporalPeriodPropertyBuilder.cs +++ b/src/EFCore.SqlServer/Metadata/Builders/TemporalPeriodPropertyBuilder.cs @@ -11,8 +11,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders; /// public class TemporalPeriodPropertyBuilder { - private readonly IMutableEntityType _entityType; - private readonly string _periodPropertyName; + private readonly PropertyBuilder _periodPropertyBuilder; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -21,10 +20,9 @@ public class TemporalPeriodPropertyBuilder /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [EntityFrameworkInternal] - public TemporalPeriodPropertyBuilder(IMutableEntityType entityType, string periodPropertyName) + public TemporalPeriodPropertyBuilder(PropertyBuilder periodPropertyBuilder) { - _entityType = entityType; - _periodPropertyName = periodPropertyName; + _periodPropertyBuilder = periodPropertyBuilder; } /// @@ -38,7 +36,7 @@ public TemporalPeriodPropertyBuilder(IMutableEntityType entityType, string perio /// The same builder instance so that multiple calls can be chained. public virtual TemporalPeriodPropertyBuilder HasColumnName(string name) { - _entityType.GetProperty(_periodPropertyName).SetColumnName(name); + _periodPropertyBuilder.HasColumnName(name); return this; } diff --git a/src/EFCore.SqlServer/Metadata/Builders/TemporalTableBuilder.cs b/src/EFCore.SqlServer/Metadata/Builders/TemporalTableBuilder.cs index 4d9a035b34c..f83c65ae6f4 100644 --- a/src/EFCore.SqlServer/Metadata/Builders/TemporalTableBuilder.cs +++ b/src/EFCore.SqlServer/Metadata/Builders/TemporalTableBuilder.cs @@ -11,7 +11,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Builders; /// public class TemporalTableBuilder { - private readonly IMutableEntityType _entityType; + private readonly EntityTypeBuilder _entityTypeBuilder; /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -20,9 +20,9 @@ public class TemporalTableBuilder /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [EntityFrameworkInternal] - public TemporalTableBuilder(IMutableEntityType entityType) + public TemporalTableBuilder(EntityTypeBuilder entityTypeBuilder) { - _entityType = entityType; + _entityTypeBuilder = entityTypeBuilder; } /// @@ -36,7 +36,7 @@ public TemporalTableBuilder(IMutableEntityType entityType) /// The same builder instance so that multiple calls can be chained. public virtual TemporalTableBuilder UseHistoryTable(string name) { - _entityType.SetHistoryTableName(name); + _entityTypeBuilder.Metadata.SetHistoryTableName(name); return this; } @@ -53,8 +53,8 @@ public virtual TemporalTableBuilder UseHistoryTable(string name) /// The same builder instance so that multiple calls can be chained. public virtual TemporalTableBuilder UseHistoryTable(string name, string? schema) { - _entityType.SetHistoryTableName(name); - _entityType.SetHistoryTableSchema(schema); + _entityTypeBuilder.Metadata.SetHistoryTableName(name); + _entityTypeBuilder.Metadata.SetHistoryTableSchema(schema); return this; } @@ -70,9 +70,10 @@ public virtual TemporalTableBuilder UseHistoryTable(string name, string? schema) /// An object that can be used to configure the period start property. public virtual TemporalPeriodPropertyBuilder HasPeriodStart(string propertyName) { - _entityType.SetPeriodStartPropertyName(propertyName); + _entityTypeBuilder.Metadata.SetPeriodStartPropertyName(propertyName); + var propertyBuilder = ConfigurePeriodProperty(propertyName); - return new TemporalPeriodPropertyBuilder(_entityType, propertyName); + return new TemporalPeriodPropertyBuilder(propertyBuilder); } /// @@ -86,9 +87,18 @@ public virtual TemporalPeriodPropertyBuilder HasPeriodStart(string propertyName) /// An object that can be used to configure the period end property. public virtual TemporalPeriodPropertyBuilder HasPeriodEnd(string propertyName) { - _entityType.SetPeriodEndPropertyName(propertyName); + _entityTypeBuilder.Metadata.SetPeriodEndPropertyName(propertyName); + var propertyBuilder = ConfigurePeriodProperty(propertyName); - return new TemporalPeriodPropertyBuilder(_entityType, propertyName); + return new TemporalPeriodPropertyBuilder(propertyBuilder); + } + + private PropertyBuilder ConfigurePeriodProperty(string propertyName) + { + var propertyBuilder = _entityTypeBuilder.Property(typeof(DateTime), propertyName, setTypeConfigurationSource: false); + propertyBuilder.ValueGeneratedOnAddOrUpdate(); + + return propertyBuilder; } #region Hidden System.Object members diff --git a/src/EFCore.SqlServer/Metadata/Builders/TemporalTableBuilder`.cs b/src/EFCore.SqlServer/Metadata/Builders/TemporalTableBuilder`.cs index 3d0dcbb68da..fd006adbc99 100644 --- a/src/EFCore.SqlServer/Metadata/Builders/TemporalTableBuilder`.cs +++ b/src/EFCore.SqlServer/Metadata/Builders/TemporalTableBuilder`.cs @@ -18,8 +18,8 @@ public class TemporalTableBuilder : TemporalTableBuilder /// doing so can result in application failures when updating to a new Entity Framework Core release. /// [EntityFrameworkInternal] - public TemporalTableBuilder(IMutableEntityType entityType) - : base(entityType) + public TemporalTableBuilder(EntityTypeBuilder entityTypeBuilder) + : base(entityTypeBuilder) { } diff --git a/src/EFCore.SqlServer/Metadata/Internal/SqlServerAnnotationNames.cs b/src/EFCore.SqlServer/Metadata/Internal/SqlServerAnnotationNames.cs index 794a6f513b2..28329eccb08 100644 --- a/src/EFCore.SqlServer/Metadata/Internal/SqlServerAnnotationNames.cs +++ b/src/EFCore.SqlServer/Metadata/Internal/SqlServerAnnotationNames.cs @@ -195,6 +195,38 @@ public static class SqlServerAnnotationNames /// public const string TemporalPeriodEndColumnName = Prefix + "TemporalPeriodEndColumnName"; + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + public const string TemporalOperationType = Prefix + "TemporalOperationType"; + + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + public const string TemporalAsOfPointInTime = Prefix + "TemporalAsOfPointInTime"; + + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + public const string TemporalRangeOperationFrom = Prefix + "TemporalRangeOperationFrom"; + + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + public const string TemporalRangeOperationTo = Prefix + "TemporalRangeOperationTo"; + /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in diff --git a/src/EFCore.SqlServer/Properties/SqlServerStrings.Designer.cs b/src/EFCore.SqlServer/Properties/SqlServerStrings.Designer.cs index 0dfc66b5855..6e4facfe6b5 100644 --- a/src/EFCore.SqlServer/Properties/SqlServerStrings.Designer.cs +++ b/src/EFCore.SqlServer/Properties/SqlServerStrings.Designer.cs @@ -252,12 +252,35 @@ public static string TemporalNavigationExpansionOnlySupportedForAsOf(object? ope operationName); /// - /// Temporal tables are not supported for table splitting scenario. Table: '{table}'. - /// - public static string TemporalNotSupportedForTableSplitting(object? table) - => string.Format( - GetString("TemporalNotSupportedForTableSplitting", nameof(table)), - table); + /// When multiple temporal entities are mapped to the same table, their period {periodType} properties must map to the same column. Issue happens for entity type '{entityType}' with period property '{periodProperty}' which is mapped to column '{periodColumn}'. Expected period column name is '{expectedColumnName}'. + /// + public static string TemporalNotSupportedForTableSplittingWithInconsistentPeriodMapping( + object? periodType, + object? entityType, + object? periodProperty, + object? periodColumn, + object? expectedColumnName) + => string.Format( + GetString( + "TemporalNotSupportedForTableSplittingWithInconsistentPeriodMapping", + nameof(periodType), + nameof(entityType), + nameof(periodProperty), + nameof(periodColumn), + nameof(expectedColumnName)), + periodType, + entityType, + periodProperty, + periodColumn, + expectedColumnName); + + /// + /// Entity type '{entityType}' should be marked as temporal because it shares table mapping with another entity that has been marked as temporal. Alternatively, other entity types that share the same table must be non-temporal. + /// + public static string TemporalAllEntitiesMappedToSameTableMustBeTemporal(object? entityType) + => string.Format( + GetString("TemporalAllEntitiesMappedToSameTableMustBeTemporal", nameof(entityType)), + entityType); /// /// Only root entity type should be marked as temporal. Entity type: '{entityType}'. @@ -331,6 +354,14 @@ public static string TemporalSetOperationOnMismatchedSources(object? entityType) GetString("TemporalSetOperationOnMismatchedSources", nameof(entityType)), entityType); + /// + /// Only '{operationName}' temporal operation is supported for entity types that own an entity mapped to a different table. + /// + public static string TemporalOwnedTypeMappedToDifferentTableOnlySupportedForAsOf(object? operationName) + => string.Format( + GetString("TemporalOwnedTypeMappedToDifferentTableOnlySupportedForAsOf", nameof(operationName)), + operationName); + /// /// An exception has been raised that is likely due to a transient failure. Consider enabling transient error resiliency by adding 'EnableRetryOnFailure' to the 'UseSqlServer' call. /// diff --git a/src/EFCore.SqlServer/Properties/SqlServerStrings.resx b/src/EFCore.SqlServer/Properties/SqlServerStrings.resx index 69e6157c25d..bcb2db15cb3 100644 --- a/src/EFCore.SqlServer/Properties/SqlServerStrings.resx +++ b/src/EFCore.SqlServer/Properties/SqlServerStrings.resx @@ -295,8 +295,11 @@ Navigation expansion is only supported for '{operationName}' temporal operation. For other operations use join manually. - - Temporal tables are not supported for table splitting scenario. Table: '{table}'. + + When multiple temporal entities are mapped to the same table, their period {periodType} properties must map to the same column. Issue happens for entity type '{entityType}' with period property '{periodProperty}' which is mapped to column '{periodColumn}'. Expected period column name is '{expectedColumnName}'. + + + Entity type '{entityType}' should be marked as temporal because it shares table mapping with another entity that has been marked as temporal. Alternatively, other entity types that share the same table must be non-temporal. Only root entity type should be marked as temporal. Entity type: '{entityType}'. @@ -325,6 +328,9 @@ Set operation can't be applied on entity '{entityType}' because temporal operations on both arguments don't match. + + Only '{operationName}' temporal operation is supported for entity types that own an entity mapped to a different table. + An exception has been raised that is likely due to a transient failure. Consider enabling transient error resiliency by adding 'EnableRetryOnFailure' to the 'UseSqlServer' call. diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerParameterBasedSqlProcessor.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerParameterBasedSqlProcessor.cs index bb89a8bd8bc..4e4b2a3eec4 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerParameterBasedSqlProcessor.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerParameterBasedSqlProcessor.cs @@ -47,17 +47,4 @@ public override SelectExpression Optimize( return (SelectExpression)new SearchConditionConvertingExpressionVisitor(Dependencies.SqlExpressionFactory) .Visit(optimizedSelectExpression); } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - protected override SelectExpression ProcessSqlNullability( - SelectExpression selectExpression, - IReadOnlyDictionary parametersValues, - out bool canCache) - => new SqlServerSqlNullabilityProcessor(Dependencies, UseRelationalNulls).Process( - selectExpression, parametersValues, out canCache); } diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs index ef91df269f9..02124f05e4e 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerQuerySqlGenerator.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.SqlServer.Metadata.Internal; namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal; @@ -98,55 +99,67 @@ protected override void GenerateLimitOffset(SelectExpression selectExpression) /// protected override Expression VisitExtension(Expression extensionExpression) { - if (extensionExpression is TemporalTableExpression temporalTableExpression) + if (extensionExpression is TableExpression tableExpression + && tableExpression.FindAnnotation(SqlServerAnnotationNames.TemporalOperationType) != null) { - Sql.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(temporalTableExpression.Name, temporalTableExpression.Schema)) + Sql.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(tableExpression.Name, tableExpression.Schema)) .Append(" FOR SYSTEM_TIME "); - switch (temporalTableExpression) + var temporalOperationType = (TemporalOperationType)tableExpression[SqlServerAnnotationNames.TemporalOperationType]!; + + switch (temporalOperationType) { - case TemporalAsOfTableExpression asOf: - Sql.Append("AS OF ") - .Append(Sql.TypeMappingSource.GetMapping(typeof(DateTime)).GenerateSqlLiteral(asOf.PointInTime)); + case TemporalOperationType.All: + Sql.Append("ALL"); break; - case TemporalFromToTableExpression fromTo: - Sql.Append("FROM ") - .Append(Sql.TypeMappingSource.GetMapping(typeof(DateTime)).GenerateSqlLiteral(fromTo.From)) - .Append(" TO ") - .Append(Sql.TypeMappingSource.GetMapping(typeof(DateTime)).GenerateSqlLiteral(fromTo.To)); + case TemporalOperationType.AsOf: + var pointInTime = (DateTime)tableExpression[SqlServerAnnotationNames.TemporalAsOfPointInTime]!; + + Sql.Append("AS OF ") + .Append(Sql.TypeMappingSource.GetMapping(typeof(DateTime)).GenerateSqlLiteral(pointInTime)); break; - case TemporalBetweenTableExpression between: - Sql.Append("BETWEEN ") - .Append(Sql.TypeMappingSource.GetMapping(typeof(DateTime)).GenerateSqlLiteral(between.From)) - .Append(" AND ") - .Append(Sql.TypeMappingSource.GetMapping(typeof(DateTime)).GenerateSqlLiteral(between.To)); - break; + case TemporalOperationType.Between: + case TemporalOperationType.ContainedIn: + case TemporalOperationType.FromTo: + var from = Sql.TypeMappingSource.GetMapping(typeof(DateTime)).GenerateSqlLiteral( + (DateTime)tableExpression[SqlServerAnnotationNames.TemporalRangeOperationFrom]!); - case TemporalContainedInTableExpression containedIn: - Sql.Append("CONTAINED IN (") - .Append(Sql.TypeMappingSource.GetMapping(typeof(DateTime)).GenerateSqlLiteral(containedIn.From)) - .Append(", ") - .Append(Sql.TypeMappingSource.GetMapping(typeof(DateTime)).GenerateSqlLiteral(containedIn.To)) - .Append(")"); - break; + var to = Sql.TypeMappingSource.GetMapping(typeof(DateTime)).GenerateSqlLiteral( + (DateTime)tableExpression[SqlServerAnnotationNames.TemporalRangeOperationTo]!); + + switch (temporalOperationType) + { + case TemporalOperationType.FromTo: + Sql.Append($"FROM {from} TO {to}"); + break; + + case TemporalOperationType.Between: + Sql.Append($"BETWEEN {from} AND {to}"); + break; + + case TemporalOperationType.ContainedIn: + Sql.Append($"CONTAINED IN ({from}, {to})"); + break; + + default: + throw new InvalidOperationException(tableExpression.Print()); + } - case TemporalAllTableExpression _: - Sql.Append("ALL"); break; default: - throw new InvalidOperationException(temporalTableExpression.Print()); + throw new InvalidOperationException(tableExpression.Print()); } - if (temporalTableExpression.Alias != null) + if (tableExpression.Alias != null) { Sql.Append(AliasSeparator) - .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(temporalTableExpression.Alias)); + .Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(tableExpression.Alias)); } - return temporalTableExpression; + return tableExpression; } return base.VisitExtension(extensionExpression); diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerQueryableMethodTranslatingExpressionVisitor.cs index 5182667721a..d4e06748297 100644 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.SqlServer/Query/Internal/SqlServerQueryableMethodTranslatingExpressionVisitor.cs @@ -1,6 +1,9 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.EntityFrameworkCore.Query.SqlExpressions; +using Microsoft.EntityFrameworkCore.SqlServer.Metadata.Internal; + namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal; /// @@ -46,6 +49,41 @@ protected SqlServerQueryableMethodTranslatingExpressionVisitor( protected override QueryableMethodTranslatingExpressionVisitor CreateSubqueryVisitor() => new SqlServerQueryableMethodTranslatingExpressionVisitor(this); + private List ExtractTableExpressions(TableExpressionBase tableExpressionBase) + { + if (tableExpressionBase is JoinExpressionBase joinExpression) + { + tableExpressionBase = joinExpression.Table; + } + + if (tableExpressionBase is TableExpression tableExpression) + { + return new List { tableExpression }; + } + + if (tableExpressionBase is SelectExpression selectExpression) + { + var result = new List(); + foreach (var table in selectExpression.Tables) + { + result.AddRange(ExtractTableExpressions(table)); + } + + return result; + } + + if (tableExpressionBase is SetOperationBase setOperationBase) + { + var result = new List(); + result.AddRange(ExtractTableExpressions(setOperationBase.Source1)); + result.AddRange(ExtractTableExpressions(setOperationBase.Source2)); + + return result; + } + + throw new InvalidOperationException("Unsupported table expression base type."); + } + /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in @@ -56,22 +94,44 @@ protected override Expression VisitExtension(Expression extensionExpression) { if (extensionExpression is TemporalQueryRootExpression queryRootExpression) { - // sql server model validator will throw if entity is mapped to multiple tables - var table = queryRootExpression.EntityType.GetTableMappings().Single().Table; - var temporalTableExpression = queryRootExpression switch + var selectExpression = RelationalDependencies.SqlExpressionFactory.Select(queryRootExpression.EntityType); + + var tableExpressions = ExtractTableExpressions(selectExpression); + foreach (var tableExpression in tableExpressions) { - TemporalAllQueryRootExpression _ => (TemporalTableExpression)new TemporalAllTableExpression(table), - TemporalAsOfQueryRootExpression asOf => new TemporalAsOfTableExpression(table, asOf.PointInTime), - TemporalBetweenQueryRootExpression between => new TemporalBetweenTableExpression(table, between.From, between.To), - TemporalContainedInQueryRootExpression containedIn => new TemporalContainedInTableExpression( - table, containedIn.From, containedIn.To), - TemporalFromToQueryRootExpression fromTo => new TemporalFromToTableExpression(table, fromTo.From, fromTo.To), - _ => throw new InvalidOperationException(queryRootExpression.Print()) - }; - - var selectExpression = RelationalDependencies.SqlExpressionFactory.Select( - queryRootExpression.EntityType, - temporalTableExpression); + switch (queryRootExpression) + { + case TemporalAllQueryRootExpression: + tableExpression[SqlServerAnnotationNames.TemporalOperationType] = TemporalOperationType.All; + break; + + case TemporalAsOfQueryRootExpression asOf: + tableExpression[SqlServerAnnotationNames.TemporalOperationType] = TemporalOperationType.AsOf; + tableExpression[SqlServerAnnotationNames.TemporalAsOfPointInTime] = asOf.PointInTime; + break; + + case TemporalBetweenQueryRootExpression between: + tableExpression[SqlServerAnnotationNames.TemporalOperationType] = TemporalOperationType.Between; + tableExpression[SqlServerAnnotationNames.TemporalRangeOperationFrom] = between.From; + tableExpression[SqlServerAnnotationNames.TemporalRangeOperationTo] = between.To; + break; + + case TemporalContainedInQueryRootExpression containedIn: + tableExpression[SqlServerAnnotationNames.TemporalOperationType] = TemporalOperationType.ContainedIn; + tableExpression[SqlServerAnnotationNames.TemporalRangeOperationFrom] = containedIn.From; + tableExpression[SqlServerAnnotationNames.TemporalRangeOperationTo] = containedIn.To; + break; + + case TemporalFromToQueryRootExpression fromTo: + tableExpression[SqlServerAnnotationNames.TemporalOperationType] = TemporalOperationType.FromTo; + tableExpression[SqlServerAnnotationNames.TemporalRangeOperationFrom] = fromTo.From; + tableExpression[SqlServerAnnotationNames.TemporalRangeOperationTo] = fromTo.To; + break; + + default: + throw new InvalidOperationException(queryRootExpression.Print()); + } + } return new ShapedQueryExpression( selectExpression, diff --git a/src/EFCore.SqlServer/Query/Internal/SqlServerSqlNullabilityProcessor.cs b/src/EFCore.SqlServer/Query/Internal/SqlServerSqlNullabilityProcessor.cs deleted file mode 100644 index 4fc33846bd0..00000000000 --- a/src/EFCore.SqlServer/Query/Internal/SqlServerSqlNullabilityProcessor.cs +++ /dev/null @@ -1,39 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Microsoft.EntityFrameworkCore.Query.SqlExpressions; - -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal; - -/// -/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to -/// the same compatibility standards as public APIs. It may be changed or removed without notice in -/// any release. You should only use it directly in your code with extreme caution and knowing that -/// doing so can result in application failures when updating to a new Entity Framework Core release. -/// -public class SqlServerSqlNullabilityProcessor : SqlNullabilityProcessor -{ - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public SqlServerSqlNullabilityProcessor( - RelationalParameterBasedSqlProcessorDependencies dependencies, - bool useRelationalNulls) - : base(dependencies, useRelationalNulls) - { - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - protected override TableExpressionBase Visit(TableExpressionBase tableExpressionBase) - => tableExpressionBase is TemporalTableExpression temporalTableExpression - ? temporalTableExpression - : base.Visit(tableExpressionBase); -} diff --git a/src/EFCore.SqlServer/Query/Internal/TemporalAllTableExpression.cs b/src/EFCore.SqlServer/Query/Internal/TemporalAllTableExpression.cs deleted file mode 100644 index c329644f7e6..00000000000 --- a/src/EFCore.SqlServer/Query/Internal/TemporalAllTableExpression.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Microsoft.EntityFrameworkCore.Query.SqlExpressions; - -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal; - -/// -/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to -/// the same compatibility standards as public APIs. It may be changed or removed without notice in -/// any release. You should only use it directly in your code with extreme caution and knowing that -/// doing so can result in application failures when updating to a new Entity Framework Core release. -/// -public class TemporalAllTableExpression : TemporalTableExpression -{ - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public TemporalAllTableExpression(ITableBase table) - : base(table) - { - } - - private TemporalAllTableExpression(string name, string? schema, string? alias) - : base(name, schema, alias) - { - } - - /// - public override TableExpressionBase Clone() - => new TemporalAllTableExpression(Name, Schema, Alias); - - /// - protected override void Print(ExpressionPrinter expressionPrinter) - { - if (!string.IsNullOrEmpty(Schema)) - { - expressionPrinter.Append(Schema).Append("."); - } - - expressionPrinter.Append(Name).Append(" FOR SYSTEM_TIME ALL"); - - if (Alias != null) - { - expressionPrinter.Append(" AS ").Append(Alias); - } - } -} diff --git a/src/EFCore.SqlServer/Query/Internal/TemporalAsOfTableExpression.cs b/src/EFCore.SqlServer/Query/Internal/TemporalAsOfTableExpression.cs deleted file mode 100644 index f9946f51a58..00000000000 --- a/src/EFCore.SqlServer/Query/Internal/TemporalAsOfTableExpression.cs +++ /dev/null @@ -1,68 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Microsoft.EntityFrameworkCore.Query.SqlExpressions; - -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal; - -/// -/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to -/// the same compatibility standards as public APIs. It may be changed or removed without notice in -/// any release. You should only use it directly in your code with extreme caution and knowing that -/// doing so can result in application failures when updating to a new Entity Framework Core release. -/// -public class TemporalAsOfTableExpression : TemporalTableExpression -{ - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public TemporalAsOfTableExpression(ITableBase table, DateTime pointInTime) - : base(table) - { - PointInTime = pointInTime; - } - - private TemporalAsOfTableExpression(string name, string? schema, string? alias, DateTime pointInTime) - : base(name, schema, alias) - { - PointInTime = pointInTime; - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public virtual DateTime PointInTime { get; } - - /// - public override TableExpressionBase Clone() - => new TemporalAsOfTableExpression(Name, Schema, Alias, PointInTime); - - /// - protected override void Print(ExpressionPrinter expressionPrinter) - { - if (!string.IsNullOrEmpty(Schema)) - { - expressionPrinter.Append(Schema).Append("."); - } - - expressionPrinter - .Append(Name) - .Append(" FOR SYSTEM_TIME AS OF ") - .Append(PointInTime.ToString()); - - if (Alias != null) - { - expressionPrinter.Append(" AS ").Append(Alias); - } - } - - /// - public override int GetHashCode() - => HashCode.Combine(base.GetHashCode(), PointInTime); -} diff --git a/src/EFCore.SqlServer/Query/Internal/TemporalBetweenTableExpression.cs b/src/EFCore.SqlServer/Query/Internal/TemporalBetweenTableExpression.cs deleted file mode 100644 index b83564ef48c..00000000000 --- a/src/EFCore.SqlServer/Query/Internal/TemporalBetweenTableExpression.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Microsoft.EntityFrameworkCore.Query.SqlExpressions; - -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal; - -/// -/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to -/// the same compatibility standards as public APIs. It may be changed or removed without notice in -/// any release. You should only use it directly in your code with extreme caution and knowing that -/// doing so can result in application failures when updating to a new Entity Framework Core release. -/// -public class TemporalBetweenTableExpression : TemporalRangeTableExpression -{ - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public TemporalBetweenTableExpression(ITableBase table, DateTime from, DateTime to) - : base(table, from, to) - { - } - - private TemporalBetweenTableExpression(string name, string? schema, string? alias, DateTime from, DateTime to) - : base(name, schema, alias, from, to) - { - } - - /// - public override TableExpressionBase Clone() - => new TemporalBetweenTableExpression(Name, Schema, Alias, From, To); - - /// - protected override void Print(ExpressionPrinter expressionPrinter) - { - if (!string.IsNullOrEmpty(Schema)) - { - expressionPrinter.Append(Schema).Append("."); - } - - expressionPrinter - .Append(Name) - .Append(" FOR SYSTEM_TIME ") - .Append("BETWEEN ") - .Append(From.ToString()) - .Append(" AND ") - .Append(To.ToString()); - - if (Alias != null) - { - expressionPrinter.Append(" AS ").Append(Alias); - } - } -} diff --git a/src/EFCore.SqlServer/Query/Internal/TemporalContainedInTableExpression.cs b/src/EFCore.SqlServer/Query/Internal/TemporalContainedInTableExpression.cs deleted file mode 100644 index bfa5334f891..00000000000 --- a/src/EFCore.SqlServer/Query/Internal/TemporalContainedInTableExpression.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Microsoft.EntityFrameworkCore.Query.SqlExpressions; - -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal; - -/// -/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to -/// the same compatibility standards as public APIs. It may be changed or removed without notice in -/// any release. You should only use it directly in your code with extreme caution and knowing that -/// doing so can result in application failures when updating to a new Entity Framework Core release. -/// -public class TemporalContainedInTableExpression : TemporalRangeTableExpression -{ - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public TemporalContainedInTableExpression(ITableBase table, DateTime from, DateTime to) - : base(table, from, to) - { - } - - private TemporalContainedInTableExpression(string name, string? schema, string? alias, DateTime from, DateTime to) - : base(name, schema, alias, from, to) - { - } - - /// - public override TableExpressionBase Clone() - => new TemporalContainedInTableExpression(Name, Schema, Alias, From, To); - - /// - protected override void Print(ExpressionPrinter expressionPrinter) - { - if (!string.IsNullOrEmpty(Schema)) - { - expressionPrinter.Append(Schema).Append("."); - } - - expressionPrinter - .Append(Name) - .Append(" FOR SYSTEM_TIME ") - .Append("CONTAINED IN (") - .Append(From.ToString()) - .Append(", ") - .Append(To.ToString()) - .Append(")"); - - if (Alias != null) - { - expressionPrinter.Append(" AS ").Append(Alias); - } - } -} diff --git a/src/EFCore.SqlServer/Query/Internal/TemporalFromToTableExpression.cs b/src/EFCore.SqlServer/Query/Internal/TemporalFromToTableExpression.cs deleted file mode 100644 index ebcc3c96d00..00000000000 --- a/src/EFCore.SqlServer/Query/Internal/TemporalFromToTableExpression.cs +++ /dev/null @@ -1,57 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Microsoft.EntityFrameworkCore.Query.SqlExpressions; - -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal; - -/// -/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to -/// the same compatibility standards as public APIs. It may be changed or removed without notice in -/// any release. You should only use it directly in your code with extreme caution and knowing that -/// doing so can result in application failures when updating to a new Entity Framework Core release. -/// -public class TemporalFromToTableExpression : TemporalRangeTableExpression -{ - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public TemporalFromToTableExpression(ITableBase table, DateTime from, DateTime to) - : base(table, from, to) - { - } - - private TemporalFromToTableExpression(string name, string? schema, string? alias, DateTime from, DateTime to) - : base(name, schema, alias, from, to) - { - } - - /// - public override TableExpressionBase Clone() - => new TemporalFromToTableExpression(Name, Schema, Alias, From, To); - - /// - protected override void Print(ExpressionPrinter expressionPrinter) - { - if (!string.IsNullOrEmpty(Schema)) - { - expressionPrinter.Append(Schema).Append("."); - } - - expressionPrinter - .Append(Name) - .Append(" FOR SYSTEM_TIME ") - .Append("FROM ") - .Append(From.ToString()) - .Append(" TO ") - .Append(To.ToString()); - - if (Alias != null) - { - expressionPrinter.Append(" AS ").Append(Alias); - } - } -} diff --git a/src/EFCore.SqlServer/Query/Internal/TemporalRangeTableExpression.cs b/src/EFCore.SqlServer/Query/Internal/TemporalOperationType.cs similarity index 79% rename from src/EFCore.SqlServer/Query/Internal/TemporalRangeTableExpression.cs rename to src/EFCore.SqlServer/Query/Internal/TemporalOperationType.cs index 55281d83aab..18a8d8a006e 100644 --- a/src/EFCore.SqlServer/Query/Internal/TemporalRangeTableExpression.cs +++ b/src/EFCore.SqlServer/Query/Internal/TemporalOperationType.cs @@ -9,7 +9,7 @@ namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal; /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// -public abstract class TemporalRangeTableExpression : TemporalTableExpression +public enum TemporalOperationType { /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -17,12 +17,7 @@ public abstract class TemporalRangeTableExpression : TemporalTableExpression /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected TemporalRangeTableExpression(ITableBase table, DateTime from, DateTime to) - : base(table) - { - From = from; - To = to; - } + All, /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -30,12 +25,7 @@ protected TemporalRangeTableExpression(ITableBase table, DateTime from, DateTime /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - protected TemporalRangeTableExpression(string name, string? schema, string? alias, DateTime from, DateTime to) - : base(name, schema, alias) - { - From = from; - To = to; - } + AsOf, /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -43,7 +33,7 @@ protected TemporalRangeTableExpression(string name, string? schema, string? alia /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual DateTime From { get; } + Between, /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to @@ -51,9 +41,14 @@ protected TemporalRangeTableExpression(string name, string? schema, string? alia /// any release. You should only use it directly in your code with extreme caution and knowing that /// doing so can result in application failures when updating to a new Entity Framework Core release. /// - public virtual DateTime To { get; } + ContainedIn, - /// - public override int GetHashCode() - => HashCode.Combine(base.GetHashCode(), From, To); + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + FromTo } + diff --git a/src/EFCore.SqlServer/Query/Internal/TemporalTableExpression.cs b/src/EFCore.SqlServer/Query/Internal/TemporalTableExpression.cs deleted file mode 100644 index 213a7bdb397..00000000000 --- a/src/EFCore.SqlServer/Query/Internal/TemporalTableExpression.cs +++ /dev/null @@ -1,74 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using Microsoft.EntityFrameworkCore.Query.SqlExpressions; - -namespace Microsoft.EntityFrameworkCore.SqlServer.Query.Internal; - -/// -/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to -/// the same compatibility standards as public APIs. It may be changed or removed without notice in -/// any release. You should only use it directly in your code with extreme caution and knowing that -/// doing so can result in application failures when updating to a new Entity Framework Core release. -/// -public abstract class TemporalTableExpression : TableExpressionBase, IClonableTableExpressionBase -{ - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - protected TemporalTableExpression(ITableBase table) - : base(table.Name.Substring(0, 1).ToLowerInvariant()) - { - Name = table.Name; - Schema = table.Schema; - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - protected TemporalTableExpression(string name, string? schema, string? alias) - : base(alias) - { - Name = name; - Schema = schema; - } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public virtual string? Schema { get; } - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public virtual string Name { get; } - - /// - public override bool Equals(object? obj) - // This should be reference equal only. - => obj != null && ReferenceEquals(this, obj); - - /// - public override int GetHashCode() - => HashCode.Combine(base.GetHashCode(), Name, Schema); - - /// - /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to - /// the same compatibility standards as public APIs. It may be changed or removed without notice in - /// any release. You should only use it directly in your code with extreme caution and knowing that - /// doing so can result in application failures when updating to a new Entity Framework Core release. - /// - public abstract TableExpressionBase Clone(); -} diff --git a/src/EFCore/Metadata/Builders/EntityTypeBuilder.cs b/src/EFCore/Metadata/Builders/EntityTypeBuilder.cs index 789827f6d8b..341cf03c75a 100644 --- a/src/EFCore/Metadata/Builders/EntityTypeBuilder.cs +++ b/src/EFCore/Metadata/Builders/EntityTypeBuilder.cs @@ -161,6 +161,32 @@ public virtual PropertyBuilder Property(Type propertyType, string propertyName) Check.NotNull(propertyType, nameof(propertyType)), Check.NotEmpty(propertyName, nameof(propertyName)), ConfigurationSource.Explicit)!.Metadata); + /// + /// Returns an object that can be used to configure a property of the entity type. + /// If no property with the given name exists, then a new property will be added. + /// + /// + /// When adding a new property, if a property with the same name exists in the entity class + /// then it will be added to the model. If no property exists in the entity class, then + /// a new shadow state property will be added. A shadow state property is one that does not have a + /// corresponding property in the entity class. The current value for the property is stored in + /// the rather than being stored in instances of the entity class. + /// + /// The type of the property to be configured. + /// The name of the property to be configured. + /// Indicates whether the type configuration source should be set. + /// An object that can be used to configure the property. + public virtual PropertyBuilder Property( + Type propertyType, + string propertyName, + bool setTypeConfigurationSource = true) + => new( + Builder.Property( + Check.NotNull(propertyType, nameof(propertyType)), + Check.NotEmpty(propertyName, nameof(propertyName)), + setTypeConfigurationSource ? ConfigurationSource.Explicit : null, + ConfigurationSource.Explicit)!.Metadata); + /// /// Returns an object that can be used to configure a property of the entity type. /// If no property with the given name exists, then a new property will be added. diff --git a/src/EFCore/Metadata/Builders/OwnedNavigationBuilder.cs b/src/EFCore/Metadata/Builders/OwnedNavigationBuilder.cs index c3c5b6ab2d9..26f81bf358c 100644 --- a/src/EFCore/Metadata/Builders/OwnedNavigationBuilder.cs +++ b/src/EFCore/Metadata/Builders/OwnedNavigationBuilder.cs @@ -170,6 +170,32 @@ public virtual PropertyBuilder Property(string propertyNam typeof(TProperty), Check.NotEmpty(propertyName, nameof(propertyName)), ConfigurationSource.Explicit)!.Metadata)); + /// + /// Returns an object that can be used to configure a property of the entity type. + /// If no property with the given name exists, then a new property will be added. + /// + /// + /// When adding a new property, if a property with the same name exists in the entity class + /// then it will be added to the model. If no property exists in the entity class, then + /// a new shadow state property will be added. A shadow state property is one that does not have a + /// corresponding property in the entity class. The current value for the property is stored in + /// the rather than being stored in instances of the entity class. + /// + /// The type of the property to be configured. + /// The name of the property to be configured. + /// Indicates whether the type configuration source should be set. + /// An object that can be used to configure the property. + public virtual PropertyBuilder Property( + Type propertyType, + string propertyName, + bool setTypeConfigurationSource = true) + => new( + DependentEntityType.Builder.Property( + Check.NotNull(propertyType, nameof(propertyType)), + Check.NotEmpty(propertyName, nameof(propertyName)), + setTypeConfigurationSource ? ConfigurationSource.Explicit : null, + ConfigurationSource.Explicit)!.Metadata); + /// /// Returns an object that can be used to configure a property of the owned entity type. /// If no property with the given name exists, then a new property will be added. diff --git a/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.ExpressionVisitors.cs b/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.ExpressionVisitors.cs index f225d6ccef6..1e89d60116d 100644 --- a/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.ExpressionVisitors.cs +++ b/src/EFCore/Query/Internal/NavigationExpandingExpressionVisitor.ExpressionVisitors.cs @@ -143,6 +143,9 @@ protected Expression ExpandNavigation( return ownedExpansion; } + // create a dummy query root to make sure that we can actually expand this navigation (later) + var _ = _extensibilityHelper.CreateQueryRoot(targetType, entityReference.QueryRootExpression); + var ownedEntityReference = new EntityReference(targetType, entityReference.QueryRootExpression); _navigationExpandingExpressionVisitor.PopulateEagerLoadedNavigations(ownedEntityReference.IncludePaths); ownedEntityReference.MarkAsOptional(); diff --git a/test/EFCore.Relational.Tests/ModelBuilding/RelationalModelBuilderGenericTestBase.cs b/test/EFCore.Relational.Tests/ModelBuilding/RelationalModelBuilderTest.cs similarity index 59% rename from test/EFCore.Relational.Tests/ModelBuilding/RelationalModelBuilderGenericTestBase.cs rename to test/EFCore.Relational.Tests/ModelBuilding/RelationalModelBuilderTest.cs index 1b888965465..eec6cde04b5 100644 --- a/test/EFCore.Relational.Tests/ModelBuilding/RelationalModelBuilderGenericTestBase.cs +++ b/test/EFCore.Relational.Tests/ModelBuilding/RelationalModelBuilderTest.cs @@ -54,6 +54,50 @@ public override TestTableBuilder ExcludeFromMigrations(bool excluded = => Wrap(TableBuilder.ExcludeFromMigrations(excluded)); } + public abstract class TestOwnedNavigationTableBuilder + where TEntity : class + { + public abstract TestOwnedNavigationTableBuilder ExcludeFromMigrations(bool excluded = true); + } + + public class GenericTestOwnedNavigationTableBuilder : TestOwnedNavigationTableBuilder, IInfrastructure> + where TEntity : class + { + public GenericTestOwnedNavigationTableBuilder(OwnedNavigationTableBuilder tableBuilder) + { + TableBuilder = tableBuilder; + } + + protected OwnedNavigationTableBuilder TableBuilder { get; } + + public OwnedNavigationTableBuilder Instance => TableBuilder; + + protected virtual TestOwnedNavigationTableBuilder Wrap(OwnedNavigationTableBuilder tableBuilder) + => new GenericTestOwnedNavigationTableBuilder(tableBuilder); + + public override TestOwnedNavigationTableBuilder ExcludeFromMigrations(bool excluded = true) + => Wrap(TableBuilder.ExcludeFromMigrations(excluded)); + } + + public class NonGenericTestOwnedNavigationTableBuilder : TestOwnedNavigationTableBuilder, IInfrastructure + where TEntity : class + { + public NonGenericTestOwnedNavigationTableBuilder(OwnedNavigationTableBuilder tableBuilder) + { + TableBuilder = tableBuilder; + } + + protected OwnedNavigationTableBuilder TableBuilder { get; } + + public OwnedNavigationTableBuilder Instance => TableBuilder; + + protected virtual TestOwnedNavigationTableBuilder Wrap(OwnedNavigationTableBuilder tableBuilder) + => new NonGenericTestOwnedNavigationTableBuilder(tableBuilder); + + public override TestOwnedNavigationTableBuilder ExcludeFromMigrations(bool excluded = true) + => Wrap(TableBuilder.ExcludeFromMigrations(excluded)); + } + public abstract class TestCheckConstraintBuilder { public abstract TestCheckConstraintBuilder HasName(string name); diff --git a/test/EFCore.Relational.Tests/ModelBuilding/RelationalTestModelBuilderExtensions.cs b/test/EFCore.Relational.Tests/ModelBuilding/RelationalTestModelBuilderExtensions.cs index ca923f58178..4c7b694d633 100644 --- a/test/EFCore.Relational.Tests/ModelBuilding/RelationalTestModelBuilderExtensions.cs +++ b/test/EFCore.Relational.Tests/ModelBuilding/RelationalTestModelBuilderExtensions.cs @@ -235,7 +235,7 @@ public static ModelBuilderTest.TestOwnedNavigationBuilder ToTable( this ModelBuilderTest.TestOwnedNavigationBuilder builder, string? name, - Action> buildAction) + Action> buildAction) where TOwnerEntity : class where TRelatedEntity : class { @@ -244,12 +244,12 @@ public static ModelBuilderTest.TestOwnedNavigationBuilder> genericBuilder: genericBuilder.Instance.ToTable( name, - b => buildAction(new RelationalModelBuilderTest.GenericTestTableBuilder(b))); + b => buildAction(new RelationalModelBuilderTest.GenericTestOwnedNavigationTableBuilder(b))); break; case IInfrastructure nongenericBuilder: nongenericBuilder.Instance.ToTable( name, - b => buildAction(new RelationalModelBuilderTest.NonGenericTestTableBuilder(b))); + b => buildAction(new RelationalModelBuilderTest.NonGenericTestOwnedNavigationTableBuilder(b))); break; } @@ -260,7 +260,7 @@ public static ModelBuilderTest.TestOwnedNavigationBuilder builder, string name, string? schema, - Action> buildAction) + Action> buildAction) where TOwnerEntity : class where TRelatedEntity : class { @@ -269,12 +269,12 @@ public static ModelBuilderTest.TestOwnedNavigationBuilder> genericBuilder: genericBuilder.Instance.ToTable( name, schema, - b => buildAction(new RelationalModelBuilderTest.GenericTestTableBuilder(b))); + b => buildAction(new RelationalModelBuilderTest.GenericTestOwnedNavigationTableBuilder(b))); break; case IInfrastructure nongenericBuilder: nongenericBuilder.Instance.ToTable( name, schema, - b => buildAction(new RelationalModelBuilderTest.NonGenericTestTableBuilder(b))); + b => buildAction(new RelationalModelBuilderTest.NonGenericTestOwnedNavigationTableBuilder(b))); break; } diff --git a/test/EFCore.Specification.Tests/Query/OwnedQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/OwnedQueryTestBase.cs index 6bda741f5ed..e12c39cfb7c 100644 --- a/test/EFCore.Specification.Tests/Query/OwnedQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/OwnedQueryTestBase.cs @@ -788,6 +788,15 @@ public virtual async Task Filter_on_indexer_using_function_argument(bool async) await myFunc(async, zipCode); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Simple_query_entity_with_owned_collection(bool async) + { + return AssertQuery( + async, + ss => ss.Set()); + } + protected virtual DbContext CreateContext() => Fixture.CreateContext(); @@ -954,6 +963,7 @@ public IReadOnlyDictionary GetEntityAsserters() var aa = (Planet)a; Assert.Equal(ee.Id, aa.Id); + Assert.Equal(ee.Name, aa.Name); Assert.Equal(ee.StarId, aa.StarId); } } @@ -1359,7 +1369,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con }); }); - modelBuilder.Entity(pb => pb.HasData(new Planet { Id = 1, StarId = 1 })); + modelBuilder.Entity(pb => pb.HasData(new Planet { Id = 1, StarId = 1, Name = "Earth" })); modelBuilder.Entity( mb => mb.HasData( @@ -1489,11 +1499,16 @@ public virtual IQueryable Set() return (IQueryable)_bartons.AsQueryable(); } + if (typeof(TEntity) == typeof(Star)) + { + return (IQueryable)_stars.AsQueryable(); + } + throw new InvalidOperationException("Invalid entity type: " + typeof(TEntity)); } private static IReadOnlyList CreatePlanets() - => new List { new() { Id = 1, StarId = 1 } }; + => new List { new() { Id = 1, StarId = 1, Name = "Earth" } }; private static IReadOnlyList CreateStars() => new List @@ -1826,6 +1841,8 @@ protected class Planet { public int Id { get; set; } + public string Name { get; set; } + public int StarId { get; set; } public Star Star { get; set; } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/OwnedQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/OwnedQuerySqlServerTest.cs index 5311459de91..a36133100fa 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/OwnedQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/OwnedQuerySqlServerTest.cs @@ -227,7 +227,7 @@ public override async Task Navigation_rewrite_on_owned_reference_followed_by_reg await base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity(async); AssertSql( - @"SELECT [p].[Id], [p].[StarId] + @"SELECT [p].[Id], [p].[Name], [p].[StarId] FROM [OwnedPerson] AS [o] LEFT JOIN [Planet] AS [p] ON [o].[PersonAddress_Country_PlanetId] = [p].[Id]"); } @@ -254,7 +254,7 @@ public override async Task Project_multiple_owned_navigations(bool async) await base.Project_multiple_owned_navigations(async); AssertSql( - @"SELECT [o].[Id], [p].[Id], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [p].[StarId] + @"SELECT [o].[Id], [p].[Id], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [p].[Name], [p].[StarId] FROM [OwnedPerson] AS [o] LEFT JOIN [Planet] AS [p] ON [o].[PersonAddress_Country_PlanetId] = [p].[Id] LEFT JOIN ( @@ -276,7 +276,7 @@ FROM [Order] AS [o0] LEFT JOIN [OwnedPerson] AS [o1] ON [o0].[ClientId] = [o1].[Id] LEFT JOIN [Planet] AS [p0] ON [o1].[PersonAddress_Country_PlanetId] = [p0].[Id] LEFT JOIN [Star] AS [s] ON [p0].[StarId] = [s].[Id] - WHERE [o].[Id] = [o0].[ClientId] AND ([s].[Id] <> 42 OR [s].[Id] IS NULL)) AS [Count], [p].[Id], [p].[StarId] + WHERE [o].[Id] = [o0].[ClientId] AND ([s].[Id] <> 42 OR [s].[Id] IS NULL)) AS [Count], [p].[Id], [p].[Name], [p].[StarId] FROM [OwnedPerson] AS [o] LEFT JOIN [Planet] AS [p] ON [o].[PersonAddress_Country_PlanetId] = [p].[Id] ORDER BY [o].[Id]"); @@ -960,7 +960,7 @@ public override async Task Project_multiple_owned_navigations_split(bool async) await base.Project_multiple_owned_navigations_split(async); AssertSql( - @"SELECT [o].[Id], [p].[Id], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [p].[StarId] + @"SELECT [o].[Id], [p].[Id], [o].[PersonAddress_AddressLine], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [p].[Name], [p].[StarId] FROM [OwnedPerson] AS [o] LEFT JOIN [Planet] AS [p] ON [o].[PersonAddress_Country_PlanetId] = [p].[Id] ORDER BY [o].[Id], [p].[Id]", @@ -1165,7 +1165,7 @@ public override async Task Projecting_collection_correlated_with_keyless_entity_ await base.Projecting_collection_correlated_with_keyless_entity_after_navigation_works_using_parent_identifiers(async); AssertSql( - @"SELECT [b].[Throned_Value], [f].[Id], [b].[Id], [p].[Id], [p].[StarId] + @"SELECT [b].[Throned_Value], [f].[Id], [b].[Id], [p].[Id], [p].[Name], [p].[StarId] FROM [Fink] AS [f] LEFT JOIN [Barton] AS [b] ON [f].[BartonId] = [b].[Id] LEFT JOIN [Planet] AS [p] ON [b].[Throned_Value] <> [p].[Id] OR [b].[Throned_Value] IS NULL diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TemporalComplexNavigationsCollectionsSharedTypeQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TemporalComplexNavigationsCollectionsSharedTypeQuerySqlServerTest.cs index f4837a9c701..d214d053913 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TemporalComplexNavigationsCollectionsSharedTypeQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TemporalComplexNavigationsCollectionsSharedTypeQuerySqlServerTest.cs @@ -1,18 +1,3956 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.EntityFrameworkCore.TestModels.ComplexNavigationsModel; +using Xunit.Abstractions; + namespace Microsoft.EntityFrameworkCore.Query; -// TODO: this now throws due to table splitting validation -//public class TemporalComplexNavigationsCollectionsSharedTypeQuerySqlServerTest : ComplexNavigationsCollectionsSharedQueryTypeRelationalTestBase< -// TemporalComplexNavigationsSharedTypeQuerySqlServerFixture> -//{ -// public TemporalComplexNavigationsCollectionsSharedTypeQuerySqlServerTest( -// TemporalComplexNavigationsSharedTypeQuerySqlServerFixture fixture, -// ITestOutputHelper testOutputHelper) -// : base(fixture) -// { -// Fixture.TestSqlLoggerFactory.Clear(); -// //Fixture.TestSqlLoggerFactory.SetTestOutputHelper(testOutputHelper); -// } -//} +public class TemporalComplexNavigationsCollectionsSharedTypeQuerySqlServerTest : ComplexNavigationsCollectionsSharedTypeQueryRelationalTestBase< + TemporalComplexNavigationsSharedTypeQuerySqlServerFixture> +{ + public TemporalComplexNavigationsCollectionsSharedTypeQuerySqlServerTest( + TemporalComplexNavigationsSharedTypeQuerySqlServerFixture fixture, + ITestOutputHelper testOutputHelper) + : base(fixture) + { + Fixture.TestSqlLoggerFactory.Clear(); + //Fixture.TestSqlLoggerFactory.SetTestOutputHelper(testOutputHelper); + } + + protected override Expression RewriteServerQueryExpression(Expression serverQueryExpression) + { + var temporalEntityTypes = new List + { + typeof(Level1), + typeof(Level2), + typeof(Level3), + typeof(Level4), + }; + + var rewriter = new TemporalPointInTimeQueryRewriter(Fixture.ChangesDate, temporalEntityTypes); + + return rewriter.Visit(serverQueryExpression); + } + + public override async Task Complex_multi_include_with_order_by_and_paging(bool async) + { + await base.Complex_multi_include_with_order_by_and_paging(async); + + AssertSql( + @"@__p_0='0' +@__p_1='10' + +SELECT [t].[Id], [t].[Date], [t].[Name], [t].[PeriodEnd], [t].[PeriodStart], [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t1].[Id], [t1].[Level2_Optional_Id], [t1].[Level2_Required_Id], [t1].[Level3_Name], [t1].[OneToMany_Optional_Inverse3Id], [t1].[OneToMany_Required_Inverse3Id], [t1].[OneToOne_Optional_PK_Inverse3Id], [t1].[PeriodEnd], [t1].[PeriodStart], [t1].[Id0], [t1].[Id00], [t3].[Id], [t3].[Level2_Optional_Id], [t3].[Level2_Required_Id], [t3].[Level3_Name], [t3].[OneToMany_Optional_Inverse3Id], [t3].[OneToMany_Required_Inverse3Id], [t3].[OneToOne_Optional_PK_Inverse3Id], [t3].[PeriodEnd], [t3].[PeriodStart], [t3].[Id0], [t3].[Id00] +FROM ( + SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] + ORDER BY [l].[Name] + OFFSET @__p_0 ROWS FETCH NEXT @__p_1 ROWS ONLY +) AS [t] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t0] ON [t].[Id] = [t0].[Level1_Required_Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t2].[Id] AS [Id0], [t2].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t2] ON [l2].[Id] = [t2].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t1] ON CASE + WHEN [t0].[OneToOne_Required_PK_Date] IS NOT NULL AND [t0].[Level1_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t0].[PeriodEnd] IS NOT NULL AND [t0].[PeriodStart] IS NOT NULL THEN [t0].[Id] +END = [t1].[OneToMany_Optional_Inverse3Id] +LEFT JOIN ( + SELECT [l5].[Id], [l5].[Level2_Optional_Id], [l5].[Level2_Required_Id], [l5].[Level3_Name], [l5].[OneToMany_Optional_Inverse3Id], [l5].[OneToMany_Required_Inverse3Id], [l5].[OneToOne_Optional_PK_Inverse3Id], [l5].[PeriodEnd], [l5].[PeriodStart], [t4].[Id] AS [Id0], [t4].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN ( + SELECT [l6].[Id], [l7].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] ON [l6].[Id] = [l7].[Id] + WHERE [l6].[OneToOne_Required_PK_Date] IS NOT NULL AND [l6].[Level1_Required_Id] IS NOT NULL AND [l6].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t4] ON [l5].[Id] = [t4].[Id] + WHERE [l5].[Level2_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t3] ON CASE + WHEN [t0].[OneToOne_Required_PK_Date] IS NOT NULL AND [t0].[Level1_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t0].[PeriodEnd] IS NOT NULL AND [t0].[PeriodStart] IS NOT NULL THEN [t0].[Id] +END = [t3].[OneToMany_Required_Inverse3Id] +ORDER BY [t].[Name], [t].[Id], [t0].[Id], [t0].[Id0], [t1].[Id], [t1].[Id0], [t1].[Id00], [t3].[Id], [t3].[Id0]"); + } + + public override async Task Complex_multi_include_with_order_by_and_paging_joins_on_correct_key(bool async) + { + await base.Complex_multi_include_with_order_by_and_paging_joins_on_correct_key(async); + + AssertSql( + @"@__p_0='0' +@__p_1='10' + +SELECT [t].[Id], [t].[Date], [t].[Name], [t].[PeriodEnd], [t].[PeriodStart], [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t1].[Id], [t1].[Id0], [t2].[Id], [t2].[Level2_Optional_Id], [t2].[Level2_Required_Id], [t2].[Level3_Name], [t2].[OneToMany_Optional_Inverse3Id], [t2].[OneToMany_Required_Inverse3Id], [t2].[OneToOne_Optional_PK_Inverse3Id], [t2].[PeriodEnd], [t2].[PeriodStart], [t2].[Id0], [t2].[Id00], [t1].[OneToOne_Required_PK_Date], [t1].[Level1_Optional_Id], [t1].[Level1_Required_Id], [t1].[Level2_Name], [t1].[OneToMany_Optional_Inverse2Id], [t1].[OneToMany_Required_Inverse2Id], [t1].[OneToOne_Optional_PK_Inverse2Id], [t1].[PeriodEnd], [t1].[PeriodStart], [t4].[Id], [t4].[Level2_Optional_Id], [t4].[Level2_Required_Id], [t4].[Level3_Name], [t4].[OneToMany_Optional_Inverse3Id], [t4].[OneToMany_Required_Inverse3Id], [t4].[OneToOne_Optional_PK_Inverse3Id], [t4].[PeriodEnd], [t4].[PeriodStart], [t4].[Id0], [t4].[Id00] +FROM ( + SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] + ORDER BY [l].[Name] + OFFSET @__p_0 ROWS FETCH NEXT @__p_1 ROWS ONLY +) AS [t] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t0] ON [t].[Id] = [t0].[Level1_Optional_Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[OneToOne_Required_PK_Date], [l2].[Level1_Optional_Id], [l2].[Level1_Required_Id], [l2].[Level2_Name], [l2].[OneToMany_Optional_Inverse2Id], [l2].[OneToMany_Required_Inverse2Id], [l2].[OneToOne_Optional_PK_Inverse2Id], [l2].[PeriodEnd], [l2].[PeriodStart], [l3].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] ON [l2].[Id] = [l3].[Id] + WHERE [l2].[OneToOne_Required_PK_Date] IS NOT NULL AND [l2].[Level1_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t1] ON [t].[Id] = [t1].[Level1_Required_Id] +LEFT JOIN ( + SELECT [l4].[Id], [l4].[Level2_Optional_Id], [l4].[Level2_Required_Id], [l4].[Level3_Name], [l4].[OneToMany_Optional_Inverse3Id], [l4].[OneToMany_Required_Inverse3Id], [l4].[OneToOne_Optional_PK_Inverse3Id], [l4].[PeriodEnd], [l4].[PeriodStart], [t3].[Id] AS [Id0], [t3].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] + INNER JOIN ( + SELECT [l5].[Id], [l6].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] ON [l5].[Id] = [l6].[Id] + WHERE [l5].[OneToOne_Required_PK_Date] IS NOT NULL AND [l5].[Level1_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t3] ON [l4].[Id] = [t3].[Id] + WHERE [l4].[Level2_Required_Id] IS NOT NULL AND [l4].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t2] ON CASE + WHEN [t0].[OneToOne_Required_PK_Date] IS NOT NULL AND [t0].[Level1_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t0].[PeriodEnd] IS NOT NULL AND [t0].[PeriodStart] IS NOT NULL THEN [t0].[Id] +END = [t2].[OneToMany_Optional_Inverse3Id] +LEFT JOIN ( + SELECT [l7].[Id], [l7].[Level2_Optional_Id], [l7].[Level2_Required_Id], [l7].[Level3_Name], [l7].[OneToMany_Optional_Inverse3Id], [l7].[OneToMany_Required_Inverse3Id], [l7].[OneToOne_Optional_PK_Inverse3Id], [l7].[PeriodEnd], [l7].[PeriodStart], [t5].[Id] AS [Id0], [t5].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] + INNER JOIN ( + SELECT [l8].[Id], [l9].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l9] ON [l8].[Id] = [l9].[Id] + WHERE [l8].[OneToOne_Required_PK_Date] IS NOT NULL AND [l8].[Level1_Required_Id] IS NOT NULL AND [l8].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t5] ON [l7].[Id] = [t5].[Id] + WHERE [l7].[Level2_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t4] ON CASE + WHEN [t1].[OneToOne_Required_PK_Date] IS NOT NULL AND [t1].[Level1_Required_Id] IS NOT NULL AND [t1].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t1].[PeriodEnd] IS NOT NULL AND [t1].[PeriodStart] IS NOT NULL THEN [t1].[Id] +END = [t4].[OneToMany_Required_Inverse3Id] +ORDER BY [t].[Name], [t].[Id], [t0].[Id], [t0].[Id0], [t1].[Id], [t1].[Id0], [t2].[Id], [t2].[Id0], [t2].[Id00], [t4].[Id], [t4].[Id0]"); + } + + public override async Task Complex_multi_include_with_order_by_and_paging_joins_on_correct_key2(bool async) + { + await base.Complex_multi_include_with_order_by_and_paging_joins_on_correct_key2(async); + + AssertSql( + @"@__p_0='0' +@__p_1='10' + +SELECT [t].[Id], [t].[Date], [t].[Name], [t].[PeriodEnd], [t].[PeriodStart], [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t1].[Id], [t1].[Level2_Optional_Id], [t1].[Level2_Required_Id], [t1].[Level3_Name], [t1].[OneToMany_Optional_Inverse3Id], [t1].[OneToMany_Required_Inverse3Id], [t1].[OneToOne_Optional_PK_Inverse3Id], [t1].[PeriodEnd], [t1].[PeriodStart], [t0].[Id0], [t1].[Id0], [t1].[Id00], [t3].[Id], [t3].[Level3_Optional_Id], [t3].[Level3_Required_Id], [t3].[Level4_Name], [t3].[OneToMany_Optional_Inverse4Id], [t3].[OneToMany_Required_Inverse4Id], [t3].[OneToOne_Optional_PK_Inverse4Id], [t3].[PeriodEnd], [t3].[PeriodStart], [t3].[Id0], [t3].[Id00], [t3].[Id000] +FROM ( + SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] + ORDER BY [l].[Name] + OFFSET @__p_0 ROWS FETCH NEXT @__p_1 ROWS ONLY +) AS [t] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t0] ON [t].[Id] = [t0].[Level1_Optional_Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t2].[Id] AS [Id0], [t2].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t2] ON [l2].[Id] = [t2].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t1] ON CASE + WHEN [t0].[OneToOne_Required_PK_Date] IS NOT NULL AND [t0].[Level1_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t0].[PeriodEnd] IS NOT NULL AND [t0].[PeriodStart] IS NOT NULL THEN [t0].[Id] +END = [t1].[Level2_Required_Id] +LEFT JOIN ( + SELECT [l5].[Id], [l5].[Level3_Optional_Id], [l5].[Level3_Required_Id], [l5].[Level4_Name], [l5].[OneToMany_Optional_Inverse4Id], [l5].[OneToMany_Required_Inverse4Id], [l5].[OneToOne_Optional_PK_Inverse4Id], [l5].[PeriodEnd], [l5].[PeriodStart], [t4].[Id] AS [Id0], [t4].[Id0] AS [Id00], [t4].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN ( + SELECT [l6].[Id], [t5].[Id] AS [Id0], [t5].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] + INNER JOIN ( + SELECT [l7].[Id], [l8].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] ON [l7].[Id] = [l8].[Id] + WHERE [l7].[OneToOne_Required_PK_Date] IS NOT NULL AND [l7].[Level1_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t5] ON [l6].[Id] = [t5].[Id] + WHERE [l6].[Level2_Required_Id] IS NOT NULL AND [l6].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t4] ON [l5].[Id] = [t4].[Id] + WHERE [l5].[Level3_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse4Id] IS NOT NULL +) AS [t3] ON CASE + WHEN [t1].[Level2_Required_Id] IS NOT NULL AND [t1].[OneToMany_Required_Inverse3Id] IS NOT NULL AND [t1].[PeriodEnd] IS NOT NULL AND [t1].[PeriodStart] IS NOT NULL THEN [t1].[Id] +END = [t3].[OneToMany_Optional_Inverse4Id] +ORDER BY [t].[Name], [t].[Id], [t0].[Id], [t0].[Id0], [t1].[Id], [t1].[Id0], [t1].[Id00], [t3].[Id], [t3].[Id0], [t3].[Id00]"); + } + + public override async Task Complex_query_with_let_collection_projection_FirstOrDefault(bool async) + { + await base.Complex_query_with_let_collection_projection_FirstOrDefault(async); + + AssertSql( + @"SELECT [l].[Id], [t0].[Id], [t0].[Id0], [t1].[Name], [t1].[Id], [t0].[c] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [t].[c], [t].[Id], [t].[Id0], [t].[OneToOne_Required_PK_Date], [t].[Level1_Required_Id], [t].[OneToMany_Required_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[OneToMany_Optional_Inverse2Id] + FROM ( + SELECT 1 AS [c], [l0].[Id], [l1].[Id] AS [Id0], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Required_Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l0].[OneToMany_Optional_Inverse2Id], ROW_NUMBER() OVER(PARTITION BY [l0].[OneToMany_Optional_Inverse2Id] ORDER BY [l0].[Id], [l1].[Id]) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND ([l0].[Level2_Name] <> N'Foo' OR [l0].[Level2_Name] IS NULL) + ) AS [t] + WHERE [t].[row] <= 1 +) AS [t0] ON [l].[Id] = [t0].[OneToMany_Optional_Inverse2Id] +OUTER APPLY ( + SELECT [l2].[Name], [l2].[Id] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + WHERE EXISTS ( + SELECT 1 + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [l2].[Id] = [l3].[OneToMany_Optional_Inverse2Id] AND [l3].[Id] = CASE + WHEN [t0].[OneToOne_Required_PK_Date] IS NOT NULL AND [t0].[Level1_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t0].[Id] + END) +) AS [t1] +ORDER BY [l].[Id], [t0].[Id], [t0].[Id0]"); + } + + public override async Task Complex_query_with_let_collection_projection_FirstOrDefault_with_ToList_on_inner_and_outer(bool async) + { + // Nested collection with ToList. Issue #23303. + await Assert.ThrowsAsync( + () => base.Complex_query_with_let_collection_projection_FirstOrDefault_with_ToList_on_inner_and_outer(async)); + + AssertSql(@"SELECT [l].[Id], [t0].[Id], [t0].[Id0], [t1].[Name], [t1].[Id], [t0].[c] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [t].[c], [t].[Id], [t].[Id0], [t].[OneToOne_Required_PK_Date], [t].[Level1_Required_Id], [t].[OneToMany_Required_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[OneToMany_Optional_Inverse2Id] + FROM ( + SELECT 1 AS [c], [l0].[Id], [l1].[Id] AS [Id0], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Required_Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l0].[OneToMany_Optional_Inverse2Id], ROW_NUMBER() OVER(PARTITION BY [l0].[OneToMany_Optional_Inverse2Id] ORDER BY [l0].[Id], [l1].[Id]) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND ([l0].[Level2_Name] <> N'Foo' OR [l0].[Level2_Name] IS NULL) + ) AS [t] + WHERE [t].[row] <= 1 +) AS [t0] ON [l].[Id] = [t0].[OneToMany_Optional_Inverse2Id] +OUTER APPLY ( + SELECT [l2].[Name], [l2].[Id] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + WHERE EXISTS ( + SELECT 1 + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [l2].[Id] = [l3].[OneToMany_Optional_Inverse2Id] AND [l3].[Id] = CASE + WHEN [t0].[OneToOne_Required_PK_Date] IS NOT NULL AND [t0].[Level1_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t0].[Id] + END) +) AS [t1] +ORDER BY [l].[Id], [t0].[Id], [t0].[Id0]"); + } + + public override async Task Filtered_include_after_different_filtered_include_different_level(bool async) + { + await base.Filtered_include_after_different_filtered_include_different_level(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t3].[Id], [t3].[OneToOne_Required_PK_Date], [t3].[Level1_Optional_Id], [t3].[Level1_Required_Id], [t3].[Level2_Name], [t3].[OneToMany_Optional_Inverse2Id], [t3].[OneToMany_Required_Inverse2Id], [t3].[OneToOne_Optional_PK_Inverse2Id], [t3].[PeriodEnd], [t3].[PeriodStart], [t3].[Id0], [t3].[Id1], [t3].[Level2_Optional_Id], [t3].[Level2_Required_Id], [t3].[Level3_Name], [t3].[OneToMany_Optional_Inverse3Id], [t3].[OneToMany_Required_Inverse3Id], [t3].[OneToOne_Optional_PK_Inverse3Id], [t3].[PeriodEnd0], [t3].[PeriodStart0], [t3].[Id00], [t3].[Id000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +OUTER APPLY ( + SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0], [t1].[Id] AS [Id1], [t1].[Level2_Optional_Id], [t1].[Level2_Required_Id], [t1].[Level3_Name], [t1].[OneToMany_Optional_Inverse3Id], [t1].[OneToMany_Required_Inverse3Id], [t1].[OneToOne_Optional_PK_Inverse3Id], [t1].[PeriodEnd] AS [PeriodEnd0], [t1].[PeriodStart] AS [PeriodStart0], [t1].[Id0] AS [Id00], [t1].[Id00] AS [Id000] + FROM ( + SELECT TOP(3) [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [l].[Id] = [l0].[OneToMany_Optional_Inverse2Id] AND ([l0].[Level2_Name] <> N'Foo' OR [l0].[Level2_Name] IS NULL) + ORDER BY [l0].[Level2_Name] + ) AS [t] + LEFT JOIN ( + SELECT [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t0].[Id00] + FROM ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t2].[Id] AS [Id0], [t2].[Id0] AS [Id00], ROW_NUMBER() OVER(PARTITION BY [l2].[OneToMany_Required_Inverse3Id] ORDER BY [l2].[Level3_Name] DESC) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t2] ON [l2].[Id] = [t2].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL AND ([l2].[Level3_Name] <> N'Bar' OR [l2].[Level3_Name] IS NULL) + ) AS [t0] + WHERE 1 < [t0].[row] + ) AS [t1] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] + END = [t1].[OneToMany_Required_Inverse3Id] +) AS [t3] +ORDER BY [l].[Id], [t3].[Level2_Name], [t3].[Id], [t3].[Id0], [t3].[OneToMany_Required_Inverse3Id], [t3].[Level3_Name] DESC, [t3].[Id1], [t3].[Id00]"); + } + + public override async Task Filtered_include_after_different_filtered_include_same_level(bool async) + { + await base.Filtered_include_after_different_filtered_include_same_level(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t1].[Id], [t1].[OneToOne_Required_PK_Date], [t1].[Level1_Optional_Id], [t1].[Level1_Required_Id], [t1].[Level2_Name], [t1].[OneToMany_Optional_Inverse2Id], [t1].[OneToMany_Required_Inverse2Id], [t1].[OneToOne_Optional_PK_Inverse2Id], [t1].[PeriodEnd], [t1].[PeriodStart], [t1].[Id0] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0] + FROM ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0], ROW_NUMBER() OVER(PARTITION BY [l0].[OneToMany_Optional_Inverse2Id] ORDER BY [l0].[Level2_Name]) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND ([l0].[Level2_Name] <> N'Foo' OR [l0].[Level2_Name] IS NULL) + ) AS [t] + WHERE [t].[row] <= 3 +) AS [t0] ON [l].[Id] = [t0].[OneToMany_Optional_Inverse2Id] +LEFT JOIN ( + SELECT [t2].[Id], [t2].[OneToOne_Required_PK_Date], [t2].[Level1_Optional_Id], [t2].[Level1_Required_Id], [t2].[Level2_Name], [t2].[OneToMany_Optional_Inverse2Id], [t2].[OneToMany_Required_Inverse2Id], [t2].[OneToOne_Optional_PK_Inverse2Id], [t2].[PeriodEnd], [t2].[PeriodStart], [t2].[Id0] + FROM ( + SELECT [l2].[Id], [l2].[OneToOne_Required_PK_Date], [l2].[Level1_Optional_Id], [l2].[Level1_Required_Id], [l2].[Level2_Name], [l2].[OneToMany_Optional_Inverse2Id], [l2].[OneToMany_Required_Inverse2Id], [l2].[OneToOne_Optional_PK_Inverse2Id], [l2].[PeriodEnd], [l2].[PeriodStart], [l3].[Id] AS [Id0], ROW_NUMBER() OVER(PARTITION BY [l2].[OneToMany_Required_Inverse2Id] ORDER BY [l2].[Level2_Name] DESC) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] ON [l2].[Id] = [l3].[Id] + WHERE [l2].[OneToOne_Required_PK_Date] IS NOT NULL AND [l2].[Level1_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse2Id] IS NOT NULL AND ([l2].[Level2_Name] <> N'Bar' OR [l2].[Level2_Name] IS NULL) + ) AS [t2] + WHERE 1 < [t2].[row] +) AS [t1] ON [l].[Id] = [t1].[OneToMany_Required_Inverse2Id] +ORDER BY [l].[Id], [t0].[OneToMany_Optional_Inverse2Id], [t0].[Level2_Name], [t0].[Id], [t0].[Id0], [t1].[OneToMany_Required_Inverse2Id], [t1].[Level2_Name] DESC, [t1].[Id]"); + } + + public override async Task Filtered_include_after_reference_navigation(bool async) + { + await base.Filtered_include_after_reference_navigation(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0], [t1].[Id], [t1].[Level2_Optional_Id], [t1].[Level2_Required_Id], [t1].[Level3_Name], [t1].[OneToMany_Optional_Inverse3Id], [t1].[OneToMany_Required_Inverse3Id], [t1].[OneToOne_Optional_PK_Inverse3Id], [t1].[PeriodEnd], [t1].[PeriodStart], [t1].[Id0], [t1].[Id00] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[Level1_Optional_Id] +LEFT JOIN ( + SELECT [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t0].[Id00] + FROM ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t2].[Id] AS [Id0], [t2].[Id0] AS [Id00], ROW_NUMBER() OVER(PARTITION BY [l2].[OneToMany_Optional_Inverse3Id] ORDER BY [l2].[Level3_Name]) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t2] ON [l2].[Id] = [t2].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL AND ([l2].[Level3_Name] <> N'Foo' OR [l2].[Level3_Name] IS NULL) + ) AS [t0] + WHERE 1 < [t0].[row] AND [t0].[row] <= 4 +) AS [t1] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END = [t1].[OneToMany_Optional_Inverse3Id] +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t1].[OneToMany_Optional_Inverse3Id], [t1].[Level3_Name], [t1].[Id], [t1].[Id0]"); + } + + public override async Task Filtered_include_and_non_filtered_include_followed_by_then_include_on_same_navigation(bool async) + { + await base.Filtered_include_and_non_filtered_include_followed_by_then_include_on_same_navigation(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t5].[Id], [t5].[OneToOne_Required_PK_Date], [t5].[Level1_Optional_Id], [t5].[Level1_Required_Id], [t5].[Level2_Name], [t5].[OneToMany_Optional_Inverse2Id], [t5].[OneToMany_Required_Inverse2Id], [t5].[OneToOne_Optional_PK_Inverse2Id], [t5].[PeriodEnd], [t5].[PeriodStart], [t5].[Id0], [t5].[Level2_Optional_Id], [t5].[Level2_Required_Id], [t5].[Level3_Name], [t5].[OneToMany_Optional_Inverse3Id], [t5].[OneToMany_Required_Inverse3Id], [t5].[OneToOne_Optional_PK_Inverse3Id], [t5].[PeriodEnd0], [t5].[PeriodStart0], [t5].[Id00], [t5].[Id01], [t5].[Id000], [t5].[Id1], [t5].[Level3_Optional_Id], [t5].[Level3_Required_Id], [t5].[Level4_Name], [t5].[OneToMany_Optional_Inverse4Id], [t5].[OneToMany_Required_Inverse4Id], [t5].[OneToOne_Optional_PK_Inverse4Id], [t5].[PeriodEnd1], [t5].[PeriodStart1], [t5].[Id02], [t5].[Id001], [t5].[Id0000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +OUTER APPLY ( + SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t0].[Id] AS [Id0], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd] AS [PeriodEnd0], [t0].[PeriodStart] AS [PeriodStart0], [t].[Id0] AS [Id00], [t0].[Id0] AS [Id01], [t0].[Id00] AS [Id000], [t2].[Id] AS [Id1], [t2].[Level3_Optional_Id], [t2].[Level3_Required_Id], [t2].[Level4_Name], [t2].[OneToMany_Optional_Inverse4Id], [t2].[OneToMany_Required_Inverse4Id], [t2].[OneToOne_Optional_PK_Inverse4Id], [t2].[PeriodEnd] AS [PeriodEnd1], [t2].[PeriodStart] AS [PeriodStart1], [t2].[Id0] AS [Id02], [t2].[Id00] AS [Id001], [t2].[Id000] AS [Id0000], [t].[c] + FROM ( + SELECT TOP(1) [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0], CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END AS [c] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [l].[Id] = [l0].[OneToMany_Optional_Inverse2Id] AND ([l0].[Level2_Name] <> N'Foo' OR [l0].[Level2_Name] IS NULL) + ORDER BY CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END + ) AS [t] + LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] + END = [t0].[OneToOne_Optional_PK_Inverse3Id] + LEFT JOIN ( + SELECT [l5].[Id], [l5].[Level3_Optional_Id], [l5].[Level3_Required_Id], [l5].[Level4_Name], [l5].[OneToMany_Optional_Inverse4Id], [l5].[OneToMany_Required_Inverse4Id], [l5].[OneToOne_Optional_PK_Inverse4Id], [l5].[PeriodEnd], [l5].[PeriodStart], [t3].[Id] AS [Id0], [t3].[Id0] AS [Id00], [t3].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN ( + SELECT [l6].[Id], [t4].[Id] AS [Id0], [t4].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] + INNER JOIN ( + SELECT [l7].[Id], [l8].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] ON [l7].[Id] = [l8].[Id] + WHERE [l7].[OneToOne_Required_PK_Date] IS NOT NULL AND [l7].[Level1_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t4] ON [l6].[Id] = [t4].[Id] + WHERE [l6].[Level2_Required_Id] IS NOT NULL AND [l6].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t3] ON [l5].[Id] = [t3].[Id] + WHERE [l5].[Level3_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse4Id] IS NOT NULL AND [l5].[Id] > 1 + ) AS [t2] ON CASE + WHEN [t0].[Level2_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse3Id] IS NOT NULL AND [t0].[PeriodEnd] IS NOT NULL AND [t0].[PeriodStart] IS NOT NULL THEN [t0].[Id] + END = [t2].[OneToMany_Optional_Inverse4Id] +) AS [t5] +ORDER BY [l].[Id], [t5].[c], [t5].[Id], [t5].[Id00], [t5].[Id0], [t5].[Id01], [t5].[Id000], [t5].[Id1], [t5].[Id02], [t5].[Id001]"); + } + + public override async Task Filtered_include_and_non_filtered_include_on_same_navigation1(bool async) + { + await base.Filtered_include_and_non_filtered_include_on_same_navigation1(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0], [t].[c] + FROM ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0], ROW_NUMBER() OVER(PARTITION BY [l0].[OneToMany_Optional_Inverse2Id] ORDER BY CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END) AS [row], CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END AS [c] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND ([l0].[Level2_Name] <> N'Foo' OR [l0].[Level2_Name] IS NULL) + ) AS [t] + WHERE [t].[row] <= 3 +) AS [t0] ON [l].[Id] = [t0].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t0].[OneToMany_Optional_Inverse2Id], [t0].[c], [t0].[Id]"); + } + + public override async Task Filtered_include_and_non_filtered_include_on_same_navigation2(bool async) + { + await base.Filtered_include_and_non_filtered_include_on_same_navigation2(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0], [t].[c] + FROM ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0], ROW_NUMBER() OVER(PARTITION BY [l0].[OneToMany_Optional_Inverse2Id] ORDER BY CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END) AS [row], CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END AS [c] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND ([l0].[Level2_Name] <> N'Foo' OR [l0].[Level2_Name] IS NULL) + ) AS [t] + WHERE [t].[row] <= 3 +) AS [t0] ON [l].[Id] = [t0].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t0].[OneToMany_Optional_Inverse2Id], [t0].[c], [t0].[Id]"); + } + + public override async Task Filtered_include_basic_OrderBy_Skip(bool async) + { + await base.Filtered_include_basic_OrderBy_Skip(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0] + FROM ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0], ROW_NUMBER() OVER(PARTITION BY [l0].[OneToMany_Optional_Inverse2Id] ORDER BY [l0].[Level2_Name]) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] + WHERE 1 < [t].[row] +) AS [t0] ON [l].[Id] = [t0].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t0].[OneToMany_Optional_Inverse2Id], [t0].[Level2_Name], [t0].[Id]"); + } + + public override async Task Filtered_include_basic_OrderBy_Skip_Take(bool async) + { + await base.Filtered_include_basic_OrderBy_Skip_Take(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0] + FROM ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0], ROW_NUMBER() OVER(PARTITION BY [l0].[OneToMany_Optional_Inverse2Id] ORDER BY [l0].[Level2_Name]) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] + WHERE 1 < [t].[row] AND [t].[row] <= 4 +) AS [t0] ON [l].[Id] = [t0].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t0].[OneToMany_Optional_Inverse2Id], [t0].[Level2_Name], [t0].[Id]"); + } + + public override async Task Filtered_include_basic_OrderBy_Take(bool async) + { + await base.Filtered_include_basic_OrderBy_Take(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0] + FROM ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0], ROW_NUMBER() OVER(PARTITION BY [l0].[OneToMany_Optional_Inverse2Id] ORDER BY [l0].[Level2_Name]) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] + WHERE [t].[row] <= 3 +) AS [t0] ON [l].[Id] = [t0].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t0].[OneToMany_Optional_Inverse2Id], [t0].[Level2_Name], [t0].[Id]"); + } + + public override async Task Filtered_include_basic_Where(bool async) + { + await base.Filtered_include_basic_Where(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [l0].[Id] > 5 +) AS [t] ON [l].[Id] = [t].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t].[Id]"); + } + + public override async Task Filtered_include_complex_three_level_with_middle_having_filter1(bool async) + { + await base.Filtered_include_complex_three_level_with_middle_having_filter1(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t8].[Id], [t8].[OneToOne_Required_PK_Date], [t8].[Level1_Optional_Id], [t8].[Level1_Required_Id], [t8].[Level2_Name], [t8].[OneToMany_Optional_Inverse2Id], [t8].[OneToMany_Required_Inverse2Id], [t8].[OneToOne_Optional_PK_Inverse2Id], [t8].[PeriodEnd], [t8].[PeriodStart], [t8].[Id0], [t8].[Id1], [t8].[Level2_Optional_Id], [t8].[Level2_Required_Id], [t8].[Level3_Name], [t8].[OneToMany_Optional_Inverse3Id], [t8].[OneToMany_Required_Inverse3Id], [t8].[OneToOne_Optional_PK_Inverse3Id], [t8].[PeriodEnd0], [t8].[PeriodStart0], [t8].[Id00], [t8].[Id000], [t8].[Id10], [t8].[Level3_Optional_Id], [t8].[Level3_Required_Id], [t8].[Level4_Name], [t8].[OneToMany_Optional_Inverse4Id], [t8].[OneToMany_Required_Inverse4Id], [t8].[OneToOne_Optional_PK_Inverse4Id], [t8].[PeriodEnd00], [t8].[PeriodStart00], [t8].[Id01], [t8].[Id0000], [t8].[Id00000], [t8].[Id2], [t8].[Level3_Optional_Id0], [t8].[Level3_Required_Id0], [t8].[Level4_Name0], [t8].[OneToMany_Optional_Inverse4Id0], [t8].[OneToMany_Required_Inverse4Id0], [t8].[OneToOne_Optional_PK_Inverse4Id0], [t8].[PeriodEnd1], [t8].[PeriodStart1], [t8].[Id02], [t8].[Id001], [t8].[Id0001] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0], [t7].[Id] AS [Id1], [t7].[Level2_Optional_Id], [t7].[Level2_Required_Id], [t7].[Level3_Name], [t7].[OneToMany_Optional_Inverse3Id], [t7].[OneToMany_Required_Inverse3Id], [t7].[OneToOne_Optional_PK_Inverse3Id], [t7].[PeriodEnd] AS [PeriodEnd0], [t7].[PeriodStart] AS [PeriodStart0], [t7].[Id0] AS [Id00], [t7].[Id00] AS [Id000], [t7].[Id1] AS [Id10], [t7].[Level3_Optional_Id], [t7].[Level3_Required_Id], [t7].[Level4_Name], [t7].[OneToMany_Optional_Inverse4Id], [t7].[OneToMany_Required_Inverse4Id], [t7].[OneToOne_Optional_PK_Inverse4Id], [t7].[PeriodEnd0] AS [PeriodEnd00], [t7].[PeriodStart0] AS [PeriodStart00], [t7].[Id01], [t7].[Id000] AS [Id0000], [t7].[Id0000] AS [Id00000], [t7].[Id2], [t7].[Level3_Optional_Id0], [t7].[Level3_Required_Id0], [t7].[Level4_Name0], [t7].[OneToMany_Optional_Inverse4Id0], [t7].[OneToMany_Required_Inverse4Id0], [t7].[OneToOne_Optional_PK_Inverse4Id0], [t7].[PeriodEnd1], [t7].[PeriodStart1], [t7].[Id02], [t7].[Id001], [t7].[Id0001], [t7].[c] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + OUTER APPLY ( + SELECT [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t0].[Id00], [t1].[Id] AS [Id1], [t1].[Level3_Optional_Id], [t1].[Level3_Required_Id], [t1].[Level4_Name], [t1].[OneToMany_Optional_Inverse4Id], [t1].[OneToMany_Required_Inverse4Id], [t1].[OneToOne_Optional_PK_Inverse4Id], [t1].[PeriodEnd] AS [PeriodEnd0], [t1].[PeriodStart] AS [PeriodStart0], [t1].[Id0] AS [Id01], [t1].[Id00] AS [Id000], [t1].[Id000] AS [Id0000], [t4].[Id] AS [Id2], [t4].[Level3_Optional_Id] AS [Level3_Optional_Id0], [t4].[Level3_Required_Id] AS [Level3_Required_Id0], [t4].[Level4_Name] AS [Level4_Name0], [t4].[OneToMany_Optional_Inverse4Id] AS [OneToMany_Optional_Inverse4Id0], [t4].[OneToMany_Required_Inverse4Id] AS [OneToMany_Required_Inverse4Id0], [t4].[OneToOne_Optional_PK_Inverse4Id] AS [OneToOne_Optional_PK_Inverse4Id0], [t4].[PeriodEnd] AS [PeriodEnd1], [t4].[PeriodStart] AS [PeriodStart1], [t4].[Id0] AS [Id02], [t4].[Id00] AS [Id001], [t4].[Id000] AS [Id0001], [t0].[c] + FROM ( + SELECT TOP(1) [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t].[Id] AS [Id0], [t].[Id0] AS [Id00], CASE + WHEN [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [l2].[Id] + END AS [c] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] ON [l2].[Id] = [t].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL AND CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END IS NOT NULL AND (CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END = [l2].[OneToMany_Optional_Inverse3Id] OR (CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END IS NULL AND [l2].[OneToMany_Optional_Inverse3Id] IS NULL)) AND ([l2].[Level3_Name] <> N'Foo' OR [l2].[Level3_Name] IS NULL) + ORDER BY CASE + WHEN [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [l2].[Id] + END + ) AS [t0] + LEFT JOIN ( + SELECT [l5].[Id], [l5].[Level3_Optional_Id], [l5].[Level3_Required_Id], [l5].[Level4_Name], [l5].[OneToMany_Optional_Inverse4Id], [l5].[OneToMany_Required_Inverse4Id], [l5].[OneToOne_Optional_PK_Inverse4Id], [l5].[PeriodEnd], [l5].[PeriodStart], [t2].[Id] AS [Id0], [t2].[Id0] AS [Id00], [t2].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN ( + SELECT [l6].[Id], [t3].[Id] AS [Id0], [t3].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] + INNER JOIN ( + SELECT [l7].[Id], [l8].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] ON [l7].[Id] = [l8].[Id] + WHERE [l7].[OneToOne_Required_PK_Date] IS NOT NULL AND [l7].[Level1_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t3] ON [l6].[Id] = [t3].[Id] + WHERE [l6].[Level2_Required_Id] IS NOT NULL AND [l6].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t2] ON [l5].[Id] = [t2].[Id] + WHERE [l5].[Level3_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse4Id] IS NOT NULL + ) AS [t1] ON CASE + WHEN [t0].[Level2_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [t0].[Id] + END = [t1].[OneToMany_Optional_Inverse4Id] + LEFT JOIN ( + SELECT [l9].[Id], [l9].[Level3_Optional_Id], [l9].[Level3_Required_Id], [l9].[Level4_Name], [l9].[OneToMany_Optional_Inverse4Id], [l9].[OneToMany_Required_Inverse4Id], [l9].[OneToOne_Optional_PK_Inverse4Id], [l9].[PeriodEnd], [l9].[PeriodStart], [t5].[Id] AS [Id0], [t5].[Id0] AS [Id00], [t5].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l9] + INNER JOIN ( + SELECT [l10].[Id], [t6].[Id] AS [Id0], [t6].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l10] + INNER JOIN ( + SELECT [l11].[Id], [l12].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l11] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l12] ON [l11].[Id] = [l12].[Id] + WHERE [l11].[OneToOne_Required_PK_Date] IS NOT NULL AND [l11].[Level1_Required_Id] IS NOT NULL AND [l11].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t6] ON [l10].[Id] = [t6].[Id] + WHERE [l10].[Level2_Required_Id] IS NOT NULL AND [l10].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t5] ON [l9].[Id] = [t5].[Id] + WHERE [l9].[Level3_Required_Id] IS NOT NULL AND [l9].[OneToMany_Required_Inverse4Id] IS NOT NULL + ) AS [t4] ON CASE + WHEN [t0].[Level2_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [t0].[Id] + END = [t4].[OneToMany_Required_Inverse4Id] + ) AS [t7] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t8] ON [l].[Id] = [t8].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t8].[Id], [t8].[Id0], [t8].[c], [t8].[Id1], [t8].[Id00], [t8].[Id000], [t8].[Id10], [t8].[Id01], [t8].[Id0000], [t8].[Id00000], [t8].[Id2], [t8].[Id02], [t8].[Id001]"); + } + + public override async Task Filtered_include_complex_three_level_with_middle_having_filter2(bool async) + { + await base.Filtered_include_complex_three_level_with_middle_having_filter2(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t8].[Id], [t8].[OneToOne_Required_PK_Date], [t8].[Level1_Optional_Id], [t8].[Level1_Required_Id], [t8].[Level2_Name], [t8].[OneToMany_Optional_Inverse2Id], [t8].[OneToMany_Required_Inverse2Id], [t8].[OneToOne_Optional_PK_Inverse2Id], [t8].[PeriodEnd], [t8].[PeriodStart], [t8].[Id0], [t8].[Id1], [t8].[Level2_Optional_Id], [t8].[Level2_Required_Id], [t8].[Level3_Name], [t8].[OneToMany_Optional_Inverse3Id], [t8].[OneToMany_Required_Inverse3Id], [t8].[OneToOne_Optional_PK_Inverse3Id], [t8].[PeriodEnd0], [t8].[PeriodStart0], [t8].[Id00], [t8].[Id000], [t8].[Id10], [t8].[Level3_Optional_Id], [t8].[Level3_Required_Id], [t8].[Level4_Name], [t8].[OneToMany_Optional_Inverse4Id], [t8].[OneToMany_Required_Inverse4Id], [t8].[OneToOne_Optional_PK_Inverse4Id], [t8].[PeriodEnd00], [t8].[PeriodStart00], [t8].[Id01], [t8].[Id0000], [t8].[Id00000], [t8].[Id2], [t8].[Level3_Optional_Id0], [t8].[Level3_Required_Id0], [t8].[Level4_Name0], [t8].[OneToMany_Optional_Inverse4Id0], [t8].[OneToMany_Required_Inverse4Id0], [t8].[OneToOne_Optional_PK_Inverse4Id0], [t8].[PeriodEnd1], [t8].[PeriodStart1], [t8].[Id02], [t8].[Id001], [t8].[Id0001] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0], [t7].[Id] AS [Id1], [t7].[Level2_Optional_Id], [t7].[Level2_Required_Id], [t7].[Level3_Name], [t7].[OneToMany_Optional_Inverse3Id], [t7].[OneToMany_Required_Inverse3Id], [t7].[OneToOne_Optional_PK_Inverse3Id], [t7].[PeriodEnd] AS [PeriodEnd0], [t7].[PeriodStart] AS [PeriodStart0], [t7].[Id0] AS [Id00], [t7].[Id00] AS [Id000], [t7].[Id1] AS [Id10], [t7].[Level3_Optional_Id], [t7].[Level3_Required_Id], [t7].[Level4_Name], [t7].[OneToMany_Optional_Inverse4Id], [t7].[OneToMany_Required_Inverse4Id], [t7].[OneToOne_Optional_PK_Inverse4Id], [t7].[PeriodEnd0] AS [PeriodEnd00], [t7].[PeriodStart0] AS [PeriodStart00], [t7].[Id01], [t7].[Id000] AS [Id0000], [t7].[Id0000] AS [Id00000], [t7].[Id2], [t7].[Level3_Optional_Id0], [t7].[Level3_Required_Id0], [t7].[Level4_Name0], [t7].[OneToMany_Optional_Inverse4Id0], [t7].[OneToMany_Required_Inverse4Id0], [t7].[OneToOne_Optional_PK_Inverse4Id0], [t7].[PeriodEnd1], [t7].[PeriodStart1], [t7].[Id02], [t7].[Id001], [t7].[Id0001], [t7].[c] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + OUTER APPLY ( + SELECT [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t0].[Id00], [t1].[Id] AS [Id1], [t1].[Level3_Optional_Id], [t1].[Level3_Required_Id], [t1].[Level4_Name], [t1].[OneToMany_Optional_Inverse4Id], [t1].[OneToMany_Required_Inverse4Id], [t1].[OneToOne_Optional_PK_Inverse4Id], [t1].[PeriodEnd] AS [PeriodEnd0], [t1].[PeriodStart] AS [PeriodStart0], [t1].[Id0] AS [Id01], [t1].[Id00] AS [Id000], [t1].[Id000] AS [Id0000], [t4].[Id] AS [Id2], [t4].[Level3_Optional_Id] AS [Level3_Optional_Id0], [t4].[Level3_Required_Id] AS [Level3_Required_Id0], [t4].[Level4_Name] AS [Level4_Name0], [t4].[OneToMany_Optional_Inverse4Id] AS [OneToMany_Optional_Inverse4Id0], [t4].[OneToMany_Required_Inverse4Id] AS [OneToMany_Required_Inverse4Id0], [t4].[OneToOne_Optional_PK_Inverse4Id] AS [OneToOne_Optional_PK_Inverse4Id0], [t4].[PeriodEnd] AS [PeriodEnd1], [t4].[PeriodStart] AS [PeriodStart1], [t4].[Id0] AS [Id02], [t4].[Id00] AS [Id001], [t4].[Id000] AS [Id0001], [t0].[c] + FROM ( + SELECT TOP(1) [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t].[Id] AS [Id0], [t].[Id0] AS [Id00], CASE + WHEN [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [l2].[Id] + END AS [c] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] ON [l2].[Id] = [t].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL AND CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END IS NOT NULL AND (CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END = [l2].[OneToMany_Optional_Inverse3Id] OR (CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END IS NULL AND [l2].[OneToMany_Optional_Inverse3Id] IS NULL)) AND ([l2].[Level3_Name] <> N'Foo' OR [l2].[Level3_Name] IS NULL) + ORDER BY CASE + WHEN [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [l2].[Id] + END + ) AS [t0] + LEFT JOIN ( + SELECT [l5].[Id], [l5].[Level3_Optional_Id], [l5].[Level3_Required_Id], [l5].[Level4_Name], [l5].[OneToMany_Optional_Inverse4Id], [l5].[OneToMany_Required_Inverse4Id], [l5].[OneToOne_Optional_PK_Inverse4Id], [l5].[PeriodEnd], [l5].[PeriodStart], [t2].[Id] AS [Id0], [t2].[Id0] AS [Id00], [t2].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN ( + SELECT [l6].[Id], [t3].[Id] AS [Id0], [t3].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] + INNER JOIN ( + SELECT [l7].[Id], [l8].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] ON [l7].[Id] = [l8].[Id] + WHERE [l7].[OneToOne_Required_PK_Date] IS NOT NULL AND [l7].[Level1_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t3] ON [l6].[Id] = [t3].[Id] + WHERE [l6].[Level2_Required_Id] IS NOT NULL AND [l6].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t2] ON [l5].[Id] = [t2].[Id] + WHERE [l5].[Level3_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse4Id] IS NOT NULL + ) AS [t1] ON CASE + WHEN [t0].[Level2_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [t0].[Id] + END = [t1].[OneToMany_Optional_Inverse4Id] + LEFT JOIN ( + SELECT [l9].[Id], [l9].[Level3_Optional_Id], [l9].[Level3_Required_Id], [l9].[Level4_Name], [l9].[OneToMany_Optional_Inverse4Id], [l9].[OneToMany_Required_Inverse4Id], [l9].[OneToOne_Optional_PK_Inverse4Id], [l9].[PeriodEnd], [l9].[PeriodStart], [t5].[Id] AS [Id0], [t5].[Id0] AS [Id00], [t5].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l9] + INNER JOIN ( + SELECT [l10].[Id], [t6].[Id] AS [Id0], [t6].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l10] + INNER JOIN ( + SELECT [l11].[Id], [l12].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l11] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l12] ON [l11].[Id] = [l12].[Id] + WHERE [l11].[OneToOne_Required_PK_Date] IS NOT NULL AND [l11].[Level1_Required_Id] IS NOT NULL AND [l11].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t6] ON [l10].[Id] = [t6].[Id] + WHERE [l10].[Level2_Required_Id] IS NOT NULL AND [l10].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t5] ON [l9].[Id] = [t5].[Id] + WHERE [l9].[Level3_Required_Id] IS NOT NULL AND [l9].[OneToMany_Required_Inverse4Id] IS NOT NULL + ) AS [t4] ON CASE + WHEN [t0].[Level2_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [t0].[Id] + END = [t4].[OneToMany_Required_Inverse4Id] + ) AS [t7] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t8] ON [l].[Id] = [t8].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t8].[Id], [t8].[Id0], [t8].[c], [t8].[Id1], [t8].[Id00], [t8].[Id000], [t8].[Id10], [t8].[Id01], [t8].[Id0000], [t8].[Id00000], [t8].[Id2], [t8].[Id02], [t8].[Id001]"); + } + + public override async Task Filtered_include_context_accessed_inside_filter(bool async) + { + await base.Filtered_include_context_accessed_inside_filter(async); + + AssertSql( + @"SELECT COUNT(*) +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l]", + // + @"@__p_0='True' + +SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0], [t].[c] + FROM ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0], ROW_NUMBER() OVER(PARTITION BY [l0].[OneToMany_Optional_Inverse2Id] ORDER BY CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END) AS [row], CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END AS [c] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND @__p_0 = CAST(1 AS bit) + ) AS [t] + WHERE [t].[row] <= 3 +) AS [t0] ON [l].[Id] = [t0].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t0].[OneToMany_Optional_Inverse2Id], [t0].[c], [t0].[Id]"); + } + + public override async Task Filtered_include_context_accessed_inside_filter_correlated(bool async) + { + await base.Filtered_include_context_accessed_inside_filter_correlated(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0], [t].[c] + FROM ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0], ROW_NUMBER() OVER(PARTITION BY [l0].[OneToMany_Optional_Inverse2Id] ORDER BY CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END) AS [row], CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END AS [c] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND ( + SELECT COUNT(*) + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + WHERE [l2].[Id] <> [l0].[Id]) > 1 + ) AS [t] + WHERE [t].[row] <= 3 +) AS [t0] ON [l].[Id] = [t0].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t0].[OneToMany_Optional_Inverse2Id], [t0].[c], [t0].[Id]"); + } + + // TODO: remove later!!!!! + public override Task Filtered_include_is_considered_loaded(bool async) + { + return base.Filtered_include_is_considered_loaded(async); + } + + public override Task Filtered_include_calling_methods_directly_on_parameter_throws(bool async) + { + return base.Filtered_include_calling_methods_directly_on_parameter_throws(async); + } + + public override Task Filtered_include_different_filter_set_on_same_navigation_twice(bool async) + { + return base.Filtered_include_different_filter_set_on_same_navigation_twice(async); + } + + public override Task Filtered_include_different_filter_set_on_same_navigation_twice_multi_level(bool async) + { + return base.Filtered_include_different_filter_set_on_same_navigation_twice_multi_level(async); + } + + public override async Task Filtered_include_multiple_multi_level_includes_with_first_level_using_filter_include_on_one_of_the_chains_only(bool async) + { + await base.Filtered_include_multiple_multi_level_includes_with_first_level_using_filter_include_on_one_of_the_chains_only(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t4].[Id], [t4].[OneToOne_Required_PK_Date], [t4].[Level1_Optional_Id], [t4].[Level1_Required_Id], [t4].[Level2_Name], [t4].[OneToMany_Optional_Inverse2Id], [t4].[OneToMany_Required_Inverse2Id], [t4].[OneToOne_Optional_PK_Inverse2Id], [t4].[PeriodEnd], [t4].[PeriodStart], [t4].[Id0], [t4].[Id1], [t4].[Id00], [t4].[Id000], [t4].[Id2], [t4].[Level2_Optional_Id], [t4].[Level2_Required_Id], [t4].[Level3_Name], [t4].[OneToMany_Optional_Inverse3Id], [t4].[OneToMany_Required_Inverse3Id], [t4].[OneToOne_Optional_PK_Inverse3Id], [t4].[PeriodEnd0], [t4].[PeriodStart0], [t4].[Id01], [t4].[Id001], [t4].[Level2_Optional_Id0], [t4].[Level2_Required_Id0], [t4].[Level3_Name0], [t4].[OneToMany_Optional_Inverse3Id0], [t4].[OneToMany_Required_Inverse3Id0], [t4].[OneToOne_Optional_PK_Inverse3Id0], [t4].[PeriodEnd1], [t4].[PeriodStart1] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +OUTER APPLY ( + SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0], [t0].[Id] AS [Id1], [t0].[Id0] AS [Id00], [t0].[Id00] AS [Id000], [t2].[Id] AS [Id2], [t2].[Level2_Optional_Id], [t2].[Level2_Required_Id], [t2].[Level3_Name], [t2].[OneToMany_Optional_Inverse3Id], [t2].[OneToMany_Required_Inverse3Id], [t2].[OneToOne_Optional_PK_Inverse3Id], [t2].[PeriodEnd] AS [PeriodEnd0], [t2].[PeriodStart] AS [PeriodStart0], [t2].[Id0] AS [Id01], [t2].[Id00] AS [Id001], [t0].[Level2_Optional_Id] AS [Level2_Optional_Id0], [t0].[Level2_Required_Id] AS [Level2_Required_Id0], [t0].[Level3_Name] AS [Level3_Name0], [t0].[OneToMany_Optional_Inverse3Id] AS [OneToMany_Optional_Inverse3Id0], [t0].[OneToMany_Required_Inverse3Id] AS [OneToMany_Required_Inverse3Id0], [t0].[OneToOne_Optional_PK_Inverse3Id] AS [OneToOne_Optional_PK_Inverse3Id0], [t0].[PeriodEnd] AS [PeriodEnd1], [t0].[PeriodStart] AS [PeriodStart1], [t].[c] + FROM ( + SELECT TOP(2) [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0], CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END AS [c] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [l].[Id] = [l0].[OneToMany_Optional_Inverse2Id] AND ([l0].[Level2_Name] <> N'Foo' OR [l0].[Level2_Name] IS NULL) + ORDER BY CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END + ) AS [t] + LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] + END = [t0].[Level2_Required_Id] + LEFT JOIN ( + SELECT [l5].[Id], [l5].[Level2_Optional_Id], [l5].[Level2_Required_Id], [l5].[Level3_Name], [l5].[OneToMany_Optional_Inverse3Id], [l5].[OneToMany_Required_Inverse3Id], [l5].[OneToOne_Optional_PK_Inverse3Id], [l5].[PeriodEnd], [l5].[PeriodStart], [t3].[Id] AS [Id0], [t3].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN ( + SELECT [l6].[Id], [l7].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] ON [l6].[Id] = [l7].[Id] + WHERE [l6].[OneToOne_Required_PK_Date] IS NOT NULL AND [l6].[Level1_Required_Id] IS NOT NULL AND [l6].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t3] ON [l5].[Id] = [t3].[Id] + WHERE [l5].[Level2_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t2] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] + END = [t2].[OneToMany_Optional_Inverse3Id] +) AS [t4] +ORDER BY [l].[Id], [t4].[c], [t4].[Id], [t4].[Id0], [t4].[Id1], [t4].[Id00], [t4].[Id000], [t4].[Id2], [t4].[Id01]"); + } + + public override async Task Filtered_include_on_ThenInclude(bool async) + { + await base.Filtered_include_on_ThenInclude(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0], [t1].[Id], [t1].[Level2_Optional_Id], [t1].[Level2_Required_Id], [t1].[Level3_Name], [t1].[OneToMany_Optional_Inverse3Id], [t1].[OneToMany_Required_Inverse3Id], [t1].[OneToOne_Optional_PK_Inverse3Id], [t1].[PeriodEnd], [t1].[PeriodStart], [t1].[Id0], [t1].[Id00] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[Level1_Optional_Id] +LEFT JOIN ( + SELECT [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t0].[Id00] + FROM ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t2].[Id] AS [Id0], [t2].[Id0] AS [Id00], ROW_NUMBER() OVER(PARTITION BY [l2].[OneToMany_Optional_Inverse3Id] ORDER BY [l2].[Level3_Name]) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t2] ON [l2].[Id] = [t2].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL AND ([l2].[Level3_Name] <> N'Foo' OR [l2].[Level3_Name] IS NULL) + ) AS [t0] + WHERE 1 < [t0].[row] AND [t0].[row] <= 4 +) AS [t1] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END = [t1].[OneToMany_Optional_Inverse3Id] +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t1].[OneToMany_Optional_Inverse3Id], [t1].[Level3_Name], [t1].[Id], [t1].[Id0]"); + } + + public override async Task Filtered_include_Skip_without_OrderBy(bool async) + { + await base.Filtered_include_Skip_without_OrderBy(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0] + FROM ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0], ROW_NUMBER() OVER(PARTITION BY [l0].[OneToMany_Optional_Inverse2Id] ORDER BY [l0].[Id], [l1].[Id]) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] + WHERE 1 < [t].[row] +) AS [t0] ON [l].[Id] = [t0].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t0].[Id]"); + } + + public override async Task Filtered_include_Take_without_OrderBy(bool async) + { + await base.Filtered_include_Take_without_OrderBy(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0] + FROM ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0], ROW_NUMBER() OVER(PARTITION BY [l0].[OneToMany_Optional_Inverse2Id] ORDER BY [l0].[Id], [l1].[Id]) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] + WHERE [t].[row] <= 1 +) AS [t0] ON [l].[Id] = [t0].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t0].[Id]"); + } + + public override async Task Filtered_include_Take_with_another_Take_on_top_level(bool async) + { + await base.Filtered_include_Take_with_another_Take_on_top_level(async); + + AssertSql( + @"@__p_0='5' + +SELECT [t].[Id], [t].[Date], [t].[Name], [t].[PeriodEnd], [t].[PeriodStart], [t2].[Id], [t2].[OneToOne_Required_PK_Date], [t2].[Level1_Optional_Id], [t2].[Level1_Required_Id], [t2].[Level2_Name], [t2].[OneToMany_Optional_Inverse2Id], [t2].[OneToMany_Required_Inverse2Id], [t2].[OneToOne_Optional_PK_Inverse2Id], [t2].[PeriodEnd], [t2].[PeriodStart], [t2].[Id0], [t2].[Level2_Optional_Id], [t2].[Level2_Required_Id], [t2].[Level3_Name], [t2].[OneToMany_Optional_Inverse3Id], [t2].[OneToMany_Required_Inverse3Id], [t2].[OneToOne_Optional_PK_Inverse3Id], [t2].[PeriodEnd0], [t2].[PeriodStart0], [t2].[Id00], [t2].[Id01], [t2].[Id000] +FROM ( + SELECT TOP(@__p_0) [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] + ORDER BY [l].[Id] +) AS [t] +OUTER APPLY ( + SELECT [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Level2_Optional_Id], [t1].[Level2_Required_Id], [t1].[Level3_Name], [t1].[OneToMany_Optional_Inverse3Id], [t1].[OneToMany_Required_Inverse3Id], [t1].[OneToOne_Optional_PK_Inverse3Id], [t1].[PeriodEnd] AS [PeriodEnd0], [t1].[PeriodStart] AS [PeriodStart0], [t0].[Id0] AS [Id00], [t1].[Id0] AS [Id01], [t1].[Id00] AS [Id000] + FROM ( + SELECT TOP(4) [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[Id] = [l0].[OneToMany_Optional_Inverse2Id] + ORDER BY [l0].[Level2_Name] DESC + ) AS [t0] + LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t3].[Id] AS [Id0], [t3].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t3] ON [l2].[Id] = [t3].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t1] ON CASE + WHEN [t0].[OneToOne_Required_PK_Date] IS NOT NULL AND [t0].[Level1_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t0].[Id] + END = [t1].[Level2_Optional_Id] +) AS [t2] +ORDER BY [t].[Id], [t2].[Level2_Name] DESC, [t2].[Id], [t2].[Id00], [t2].[Id0], [t2].[Id01]"); + } + + public override async Task Filtered_include_ThenInclude_OrderBy(bool async) + { + await base.Filtered_include_ThenInclude_OrderBy(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t1].[Id], [t1].[OneToOne_Required_PK_Date], [t1].[Level1_Optional_Id], [t1].[Level1_Required_Id], [t1].[Level2_Name], [t1].[OneToMany_Optional_Inverse2Id], [t1].[OneToMany_Required_Inverse2Id], [t1].[OneToOne_Optional_PK_Inverse2Id], [t1].[PeriodEnd], [t1].[PeriodStart], [t1].[Id0], [t1].[Id1], [t1].[Level2_Optional_Id], [t1].[Level2_Required_Id], [t1].[Level3_Name], [t1].[OneToMany_Optional_Inverse3Id], [t1].[OneToMany_Required_Inverse3Id], [t1].[OneToOne_Optional_PK_Inverse3Id], [t1].[PeriodEnd0], [t1].[PeriodStart0], [t1].[Id00], [t1].[Id000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0], [t0].[Id] AS [Id1], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd] AS [PeriodEnd0], [t0].[PeriodStart] AS [PeriodStart0], [t0].[Id0] AS [Id00], [t0].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t].[Id] AS [Id0], [t].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] ON [l2].[Id] = [t].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t0] ON CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END = [t0].[OneToMany_Optional_Inverse3Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t1] ON [l].[Id] = [t1].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t1].[Level2_Name], [t1].[Id], [t1].[Id0], [t1].[Level3_Name] DESC, [t1].[Id1], [t1].[Id00]"); + } + + public override async Task Filtered_include_variable_used_inside_filter(bool async) + { + await base.Filtered_include_variable_used_inside_filter(async); + + AssertSql( + @"@__prm_0='Foo' (Size = 4000) + +SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0], [t].[c] + FROM ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0], ROW_NUMBER() OVER(PARTITION BY [l0].[OneToMany_Optional_Inverse2Id] ORDER BY CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END) AS [row], CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END AS [c] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND ([l0].[Level2_Name] <> @__prm_0 OR [l0].[Level2_Name] IS NULL) + ) AS [t] + WHERE [t].[row] <= 3 +) AS [t0] ON [l].[Id] = [t0].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t0].[OneToMany_Optional_Inverse2Id], [t0].[c], [t0].[Id]"); + } + + public override async Task Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_FirstOrDefault_on_top_level(bool async) + { + await base.Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_FirstOrDefault_on_top_level(async); + + AssertSql( + @"SELECT [t].[Id], [t].[Date], [t].[Name], [t].[PeriodEnd], [t].[PeriodStart], [t2].[Id], [t2].[OneToOne_Required_PK_Date], [t2].[Level1_Optional_Id], [t2].[Level1_Required_Id], [t2].[Level2_Name], [t2].[OneToMany_Optional_Inverse2Id], [t2].[OneToMany_Required_Inverse2Id], [t2].[OneToOne_Optional_PK_Inverse2Id], [t2].[PeriodEnd], [t2].[PeriodStart], [t2].[Id0], [t2].[Level2_Optional_Id], [t2].[Level2_Required_Id], [t2].[Level3_Name], [t2].[OneToMany_Optional_Inverse3Id], [t2].[OneToMany_Required_Inverse3Id], [t2].[OneToOne_Optional_PK_Inverse3Id], [t2].[PeriodEnd0], [t2].[PeriodStart0], [t2].[Id00], [t2].[Id01], [t2].[Id000] +FROM ( + SELECT TOP(1) [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] + ORDER BY [l].[Id] +) AS [t] +OUTER APPLY ( + SELECT [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Level2_Optional_Id], [t1].[Level2_Required_Id], [t1].[Level3_Name], [t1].[OneToMany_Optional_Inverse3Id], [t1].[OneToMany_Required_Inverse3Id], [t1].[OneToOne_Optional_PK_Inverse3Id], [t1].[PeriodEnd] AS [PeriodEnd0], [t1].[PeriodStart] AS [PeriodStart0], [t0].[Id0] AS [Id00], [t1].[Id0] AS [Id01], [t1].[Id00] AS [Id000] + FROM ( + SELECT TOP(40) [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[Id] = [l0].[OneToMany_Optional_Inverse2Id] + ) AS [t0] + LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t3].[Id] AS [Id0], [t3].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t3] ON [l2].[Id] = [t3].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t1] ON CASE + WHEN [t0].[OneToOne_Required_PK_Date] IS NOT NULL AND [t0].[Level1_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t0].[Id] + END = [t1].[Level2_Optional_Id] +) AS [t2] +ORDER BY [t].[Id], [t2].[Id], [t2].[Id00], [t2].[Id0], [t2].[Id01]"); + } + + public override async Task Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_unordered_Take_on_top_level(bool async) + { + await base.Filtered_include_with_Take_without_order_by_followed_by_ThenInclude_and_unordered_Take_on_top_level(async); + + AssertSql( + @"@__p_0='30' + +SELECT [t].[Id], [t].[Date], [t].[Name], [t].[PeriodEnd], [t].[PeriodStart], [t2].[Id], [t2].[OneToOne_Required_PK_Date], [t2].[Level1_Optional_Id], [t2].[Level1_Required_Id], [t2].[Level2_Name], [t2].[OneToMany_Optional_Inverse2Id], [t2].[OneToMany_Required_Inverse2Id], [t2].[OneToOne_Optional_PK_Inverse2Id], [t2].[PeriodEnd], [t2].[PeriodStart], [t2].[Id0], [t2].[Level2_Optional_Id], [t2].[Level2_Required_Id], [t2].[Level3_Name], [t2].[OneToMany_Optional_Inverse3Id], [t2].[OneToMany_Required_Inverse3Id], [t2].[OneToOne_Optional_PK_Inverse3Id], [t2].[PeriodEnd0], [t2].[PeriodStart0], [t2].[Id00], [t2].[Id01], [t2].[Id000] +FROM ( + SELECT TOP(@__p_0) [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] + ORDER BY [l].[Id] +) AS [t] +OUTER APPLY ( + SELECT [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Level2_Optional_Id], [t1].[Level2_Required_Id], [t1].[Level3_Name], [t1].[OneToMany_Optional_Inverse3Id], [t1].[OneToMany_Required_Inverse3Id], [t1].[OneToOne_Optional_PK_Inverse3Id], [t1].[PeriodEnd] AS [PeriodEnd0], [t1].[PeriodStart] AS [PeriodStart0], [t0].[Id0] AS [Id00], [t1].[Id0] AS [Id01], [t1].[Id00] AS [Id000] + FROM ( + SELECT TOP(40) [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[Id] = [l0].[OneToMany_Optional_Inverse2Id] + ) AS [t0] + LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t3].[Id] AS [Id0], [t3].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t3] ON [l2].[Id] = [t3].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t1] ON CASE + WHEN [t0].[OneToOne_Required_PK_Date] IS NOT NULL AND [t0].[Level1_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t0].[Id] + END = [t1].[Level2_Optional_Id] +) AS [t2] +ORDER BY [t].[Id], [t2].[Id], [t2].[Id00], [t2].[Id0], [t2].[Id01]"); + } + + public override async Task Filtered_ThenInclude_OrderBy(bool async) + { + await base.Filtered_ThenInclude_OrderBy(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t1].[Id], [t1].[OneToOne_Required_PK_Date], [t1].[Level1_Optional_Id], [t1].[Level1_Required_Id], [t1].[Level2_Name], [t1].[OneToMany_Optional_Inverse2Id], [t1].[OneToMany_Required_Inverse2Id], [t1].[OneToOne_Optional_PK_Inverse2Id], [t1].[PeriodEnd], [t1].[PeriodStart], [t1].[Id0], [t1].[Id1], [t1].[Level2_Optional_Id], [t1].[Level2_Required_Id], [t1].[Level3_Name], [t1].[OneToMany_Optional_Inverse3Id], [t1].[OneToMany_Required_Inverse3Id], [t1].[OneToOne_Optional_PK_Inverse3Id], [t1].[PeriodEnd0], [t1].[PeriodStart0], [t1].[Id00], [t1].[Id000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0], [t0].[Id] AS [Id1], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd] AS [PeriodEnd0], [t0].[PeriodStart] AS [PeriodStart0], [t0].[Id0] AS [Id00], [t0].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t].[Id] AS [Id0], [t].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] ON [l2].[Id] = [t].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t0] ON CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END = [t0].[OneToMany_Optional_Inverse3Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t1] ON [l].[Id] = [t1].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t1].[Id], [t1].[Id0], [t1].[Level3_Name], [t1].[Id1], [t1].[Id00]"); + } + + public override async Task FirstOrDefault_with_predicate_on_correlated_collection_in_projection(bool async) + { + await base.FirstOrDefault_with_predicate_on_correlated_collection_in_projection(async); + + AssertSql( + @"SELECT [l].[Id], [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart] + FROM ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], ROW_NUMBER() OVER(PARTITION BY [l0].[OneToMany_Optional_Inverse2Id], CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END ORDER BY [l0].[Id], [l1].[Id]) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] + WHERE [t].[row] <= 1 +) AS [t0] ON [l].[Id] = [t0].[OneToMany_Optional_Inverse2Id] AND [l].[Id] = CASE + WHEN [t0].[OneToOne_Required_PK_Date] IS NOT NULL AND [t0].[Level1_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t0].[Id] +END"); + } + + public override async Task Filtered_include_OrderBy(bool async) + { + await base.Filtered_include_OrderBy(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t].[Level2_Name], [t].[Id]"); + } + + public override async Task Filtered_include_same_filter_set_on_same_navigation_twice(bool async) + { + await base.Filtered_include_same_filter_set_on_same_navigation_twice(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0], [t].[c] + FROM ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0], ROW_NUMBER() OVER(PARTITION BY [l0].[OneToMany_Optional_Inverse2Id] ORDER BY CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END DESC) AS [row], CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END AS [c] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND ([l0].[Level2_Name] <> N'Foo' OR [l0].[Level2_Name] IS NULL) + ) AS [t] + WHERE [t].[row] <= 2 +) AS [t0] ON [l].[Id] = [t0].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t0].[OneToMany_Optional_Inverse2Id], [t0].[c] DESC, [t0].[Id]"); + } + + public override async Task Filtered_include_same_filter_set_on_same_navigation_twice_followed_by_ThenIncludes(bool async) + { + await base.Filtered_include_same_filter_set_on_same_navigation_twice_followed_by_ThenIncludes(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t4].[Id], [t4].[OneToOne_Required_PK_Date], [t4].[Level1_Optional_Id], [t4].[Level1_Required_Id], [t4].[Level2_Name], [t4].[OneToMany_Optional_Inverse2Id], [t4].[OneToMany_Required_Inverse2Id], [t4].[OneToOne_Optional_PK_Inverse2Id], [t4].[PeriodEnd], [t4].[PeriodStart], [t4].[Id0], [t4].[Id1], [t4].[Id00], [t4].[Id000], [t4].[Id2], [t4].[Level2_Optional_Id], [t4].[Level2_Required_Id], [t4].[Level3_Name], [t4].[OneToMany_Optional_Inverse3Id], [t4].[OneToMany_Required_Inverse3Id], [t4].[OneToOne_Optional_PK_Inverse3Id], [t4].[PeriodEnd0], [t4].[PeriodStart0], [t4].[Id01], [t4].[Id001], [t4].[Level2_Optional_Id0], [t4].[Level2_Required_Id0], [t4].[Level3_Name0], [t4].[OneToMany_Optional_Inverse3Id0], [t4].[OneToMany_Required_Inverse3Id0], [t4].[OneToOne_Optional_PK_Inverse3Id0], [t4].[PeriodEnd1], [t4].[PeriodStart1] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +OUTER APPLY ( + SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0], [t0].[Id] AS [Id1], [t0].[Id0] AS [Id00], [t0].[Id00] AS [Id000], [t2].[Id] AS [Id2], [t2].[Level2_Optional_Id], [t2].[Level2_Required_Id], [t2].[Level3_Name], [t2].[OneToMany_Optional_Inverse3Id], [t2].[OneToMany_Required_Inverse3Id], [t2].[OneToOne_Optional_PK_Inverse3Id], [t2].[PeriodEnd] AS [PeriodEnd0], [t2].[PeriodStart] AS [PeriodStart0], [t2].[Id0] AS [Id01], [t2].[Id00] AS [Id001], [t0].[Level2_Optional_Id] AS [Level2_Optional_Id0], [t0].[Level2_Required_Id] AS [Level2_Required_Id0], [t0].[Level3_Name] AS [Level3_Name0], [t0].[OneToMany_Optional_Inverse3Id] AS [OneToMany_Optional_Inverse3Id0], [t0].[OneToMany_Required_Inverse3Id] AS [OneToMany_Required_Inverse3Id0], [t0].[OneToOne_Optional_PK_Inverse3Id] AS [OneToOne_Optional_PK_Inverse3Id0], [t0].[PeriodEnd] AS [PeriodEnd1], [t0].[PeriodStart] AS [PeriodStart1], [t].[c] + FROM ( + SELECT TOP(2) [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0], CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END AS [c] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [l].[Id] = [l0].[OneToMany_Optional_Inverse2Id] AND ([l0].[Level2_Name] <> N'Foo' OR [l0].[Level2_Name] IS NULL) + ORDER BY CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END + ) AS [t] + LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] + END = [t0].[Level2_Required_Id] + LEFT JOIN ( + SELECT [l5].[Id], [l5].[Level2_Optional_Id], [l5].[Level2_Required_Id], [l5].[Level3_Name], [l5].[OneToMany_Optional_Inverse3Id], [l5].[OneToMany_Required_Inverse3Id], [l5].[OneToOne_Optional_PK_Inverse3Id], [l5].[PeriodEnd], [l5].[PeriodStart], [t3].[Id] AS [Id0], [t3].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN ( + SELECT [l6].[Id], [l7].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] ON [l6].[Id] = [l7].[Id] + WHERE [l6].[OneToOne_Required_PK_Date] IS NOT NULL AND [l6].[Level1_Required_Id] IS NOT NULL AND [l6].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t3] ON [l5].[Id] = [t3].[Id] + WHERE [l5].[Level2_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t2] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] + END = [t2].[OneToMany_Optional_Inverse3Id] +) AS [t4] +ORDER BY [l].[Id], [t4].[c], [t4].[Id], [t4].[Id0], [t4].[Id1], [t4].[Id00], [t4].[Id000], [t4].[Id2], [t4].[Id01]"); + } + + public override async Task Filtered_include_Skip_Take_with_another_Skip_Take_on_top_level(bool async) + { + await base.Filtered_include_Skip_Take_with_another_Skip_Take_on_top_level(async); + + AssertSql( + @"@__p_0='10' +@__p_1='5' + +SELECT [t].[Id], [t].[Date], [t].[Name], [t].[PeriodEnd], [t].[PeriodStart], [t2].[Id], [t2].[OneToOne_Required_PK_Date], [t2].[Level1_Optional_Id], [t2].[Level1_Required_Id], [t2].[Level2_Name], [t2].[OneToMany_Optional_Inverse2Id], [t2].[OneToMany_Required_Inverse2Id], [t2].[OneToOne_Optional_PK_Inverse2Id], [t2].[PeriodEnd], [t2].[PeriodStart], [t2].[Id0], [t2].[Level2_Optional_Id], [t2].[Level2_Required_Id], [t2].[Level3_Name], [t2].[OneToMany_Optional_Inverse3Id], [t2].[OneToMany_Required_Inverse3Id], [t2].[OneToOne_Optional_PK_Inverse3Id], [t2].[PeriodEnd0], [t2].[PeriodStart0], [t2].[Id00], [t2].[Id01], [t2].[Id000] +FROM ( + SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] + ORDER BY [l].[Id] DESC + OFFSET @__p_0 ROWS FETCH NEXT @__p_1 ROWS ONLY +) AS [t] +OUTER APPLY ( + SELECT [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Level2_Optional_Id], [t1].[Level2_Required_Id], [t1].[Level3_Name], [t1].[OneToMany_Optional_Inverse3Id], [t1].[OneToMany_Required_Inverse3Id], [t1].[OneToOne_Optional_PK_Inverse3Id], [t1].[PeriodEnd] AS [PeriodEnd0], [t1].[PeriodStart] AS [PeriodStart0], [t0].[Id0] AS [Id00], [t1].[Id0] AS [Id01], [t1].[Id00] AS [Id000] + FROM ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[Id] = [l0].[OneToMany_Optional_Inverse2Id] + ORDER BY [l0].[Level2_Name] DESC + OFFSET 2 ROWS FETCH NEXT 4 ROWS ONLY + ) AS [t0] + LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t3].[Id] AS [Id0], [t3].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t3] ON [l2].[Id] = [t3].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t1] ON CASE + WHEN [t0].[OneToOne_Required_PK_Date] IS NOT NULL AND [t0].[Level1_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t0].[Id] + END = [t1].[Level2_Optional_Id] +) AS [t2] +ORDER BY [t].[Id] DESC, [t2].[Level2_Name] DESC, [t2].[Id], [t2].[Id00], [t2].[Id0], [t2].[Id01]"); + } + + public override async Task Include_after_SelectMany(bool async) + { + await base.Include_after_SelectMany(async); + + AssertSql( + @"SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [l].[Id], [t].[Id0], [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t0].[Id00] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +INNER JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[OneToMany_Required_Inverse2Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] +END = [t0].[OneToMany_Optional_Inverse3Id] +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0]"); + } + + public override async Task Include_and_ThenInclude_collections_followed_by_projecting_the_first_collection(bool async) + { + await base.Include_and_ThenInclude_collections_followed_by_projecting_the_first_collection(async); + + AssertSql( + @"SELECT [l].[Id], [t1].[Id], [t1].[OneToOne_Required_PK_Date], [t1].[Level1_Optional_Id], [t1].[Level1_Required_Id], [t1].[Level2_Name], [t1].[OneToMany_Optional_Inverse2Id], [t1].[OneToMany_Required_Inverse2Id], [t1].[OneToOne_Optional_PK_Inverse2Id], [t1].[PeriodEnd], [t1].[PeriodStart], [t1].[Id0], [t1].[Level2_Optional_Id], [t1].[Level2_Required_Id], [t1].[Level3_Name], [t1].[OneToMany_Optional_Inverse3Id], [t1].[OneToMany_Required_Inverse3Id], [t1].[OneToOne_Optional_PK_Inverse3Id], [t1].[PeriodEnd0], [t1].[PeriodStart0], [t1].[Id1], [t1].[Id00], [t1].[Id000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [t0].[Id] AS [Id0], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd] AS [PeriodEnd0], [t0].[PeriodStart] AS [PeriodStart0], [l1].[Id] AS [Id1], [t0].[Id0] AS [Id00], [t0].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t].[Id] AS [Id0], [t].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] ON [l2].[Id] = [t].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t0] ON CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END = [t0].[OneToOne_Optional_PK_Inverse3Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t1] ON [l].[Id] = [t1].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t1].[Id], [t1].[Id1], [t1].[Id0], [t1].[Id00]"); + } + + public override async Task Include_collection(bool async) + { + await base.Include_collection(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t].[Id]"); + } + + public override async Task Include_collection_and_another_navigation_chain_followed_by_projecting_the_first_collection(bool async) + { + await base.Include_collection_and_another_navigation_chain_followed_by_projecting_the_first_collection(async); + + AssertSql( + @"SELECT [l].[Id], [t4].[Id], [t4].[OneToOne_Required_PK_Date], [t4].[Level1_Optional_Id], [t4].[Level1_Required_Id], [t4].[Level2_Name], [t4].[OneToMany_Optional_Inverse2Id], [t4].[OneToMany_Required_Inverse2Id], [t4].[OneToOne_Optional_PK_Inverse2Id], [t4].[PeriodEnd], [t4].[PeriodStart], [t4].[Id0], [t4].[Level2_Optional_Id], [t4].[Level2_Required_Id], [t4].[Level3_Name], [t4].[OneToMany_Optional_Inverse3Id], [t4].[OneToMany_Required_Inverse3Id], [t4].[OneToOne_Optional_PK_Inverse3Id], [t4].[PeriodEnd0], [t4].[PeriodStart0], [t4].[Id1], [t4].[Level3_Optional_Id], [t4].[Level3_Required_Id], [t4].[Level4_Name], [t4].[OneToMany_Optional_Inverse4Id], [t4].[OneToMany_Required_Inverse4Id], [t4].[OneToOne_Optional_PK_Inverse4Id], [t4].[PeriodEnd1], [t4].[PeriodStart1], [t4].[Id2], [t4].[Id00], [t4].[Id000], [t4].[Id01], [t4].[Id001], [t4].[Id0000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [t0].[Id] AS [Id0], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd] AS [PeriodEnd0], [t0].[PeriodStart] AS [PeriodStart0], [t1].[Id] AS [Id1], [t1].[Level3_Optional_Id], [t1].[Level3_Required_Id], [t1].[Level4_Name], [t1].[OneToMany_Optional_Inverse4Id], [t1].[OneToMany_Required_Inverse4Id], [t1].[OneToOne_Optional_PK_Inverse4Id], [t1].[PeriodEnd] AS [PeriodEnd1], [t1].[PeriodStart] AS [PeriodStart1], [l1].[Id] AS [Id2], [t0].[Id0] AS [Id00], [t0].[Id00] AS [Id000], [t1].[Id0] AS [Id01], [t1].[Id00] AS [Id001], [t1].[Id000] AS [Id0000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t].[Id] AS [Id0], [t].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] ON [l2].[Id] = [t].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t0] ON CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END = [t0].[OneToOne_Optional_PK_Inverse3Id] + LEFT JOIN ( + SELECT [l5].[Id], [l5].[Level3_Optional_Id], [l5].[Level3_Required_Id], [l5].[Level4_Name], [l5].[OneToMany_Optional_Inverse4Id], [l5].[OneToMany_Required_Inverse4Id], [l5].[OneToOne_Optional_PK_Inverse4Id], [l5].[PeriodEnd], [l5].[PeriodStart], [t2].[Id] AS [Id0], [t2].[Id0] AS [Id00], [t2].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN ( + SELECT [l6].[Id], [t3].[Id] AS [Id0], [t3].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] + INNER JOIN ( + SELECT [l7].[Id], [l8].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] ON [l7].[Id] = [l8].[Id] + WHERE [l7].[OneToOne_Required_PK_Date] IS NOT NULL AND [l7].[Level1_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t3] ON [l6].[Id] = [t3].[Id] + WHERE [l6].[Level2_Required_Id] IS NOT NULL AND [l6].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t2] ON [l5].[Id] = [t2].[Id] + WHERE [l5].[Level3_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse4Id] IS NOT NULL + ) AS [t1] ON CASE + WHEN [t0].[Level2_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse3Id] IS NOT NULL AND [t0].[PeriodEnd] IS NOT NULL AND [t0].[PeriodStart] IS NOT NULL THEN [t0].[Id] + END = [t1].[Level3_Optional_Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t4] ON [l].[Id] = [t4].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t4].[Id], [t4].[Id2], [t4].[Id0], [t4].[Id00], [t4].[Id000], [t4].[Id1], [t4].[Id01], [t4].[Id001]"); + } + + public override async Task Include_collection_followed_by_complex_includes_and_projecting_the_included_collection(bool async) + { + await base.Include_collection_followed_by_complex_includes_and_projecting_the_included_collection(async); + + AssertSql( + @"SELECT [l].[Id], [t9].[Id], [t9].[OneToOne_Required_PK_Date], [t9].[Level1_Optional_Id], [t9].[Level1_Required_Id], [t9].[Level2_Name], [t9].[OneToMany_Optional_Inverse2Id], [t9].[OneToMany_Required_Inverse2Id], [t9].[OneToOne_Optional_PK_Inverse2Id], [t9].[PeriodEnd], [t9].[PeriodStart], [t9].[Id0], [t9].[Level2_Optional_Id], [t9].[Level2_Required_Id], [t9].[Level3_Name], [t9].[OneToMany_Optional_Inverse3Id], [t9].[OneToMany_Required_Inverse3Id], [t9].[OneToOne_Optional_PK_Inverse3Id], [t9].[PeriodEnd0], [t9].[PeriodStart0], [t9].[Id1], [t9].[Level3_Optional_Id], [t9].[Level3_Required_Id], [t9].[Level4_Name], [t9].[OneToMany_Optional_Inverse4Id], [t9].[OneToMany_Required_Inverse4Id], [t9].[OneToOne_Optional_PK_Inverse4Id], [t9].[PeriodEnd1], [t9].[PeriodStart1], [t9].[Id2], [t9].[Level2_Optional_Id0], [t9].[Level2_Required_Id0], [t9].[Level3_Name0], [t9].[OneToMany_Optional_Inverse3Id0], [t9].[OneToMany_Required_Inverse3Id0], [t9].[OneToOne_Optional_PK_Inverse3Id0], [t9].[PeriodEnd2], [t9].[PeriodStart2], [t9].[Id3], [t9].[Id00], [t9].[Id000], [t9].[Id01], [t9].[Id001], [t9].[Id0000], [t9].[Id02], [t9].[Id002], [t9].[Id4], [t9].[Level3_Optional_Id0], [t9].[Level3_Required_Id0], [t9].[Level4_Name0], [t9].[OneToMany_Optional_Inverse4Id0], [t9].[OneToMany_Required_Inverse4Id0], [t9].[OneToOne_Optional_PK_Inverse4Id0], [t9].[PeriodEnd3], [t9].[PeriodStart3], [t9].[Id03], [t9].[Id003], [t9].[Id0001] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [t0].[Id] AS [Id0], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd] AS [PeriodEnd0], [t0].[PeriodStart] AS [PeriodStart0], [t1].[Id] AS [Id1], [t1].[Level3_Optional_Id], [t1].[Level3_Required_Id], [t1].[Level4_Name], [t1].[OneToMany_Optional_Inverse4Id], [t1].[OneToMany_Required_Inverse4Id], [t1].[OneToOne_Optional_PK_Inverse4Id], [t1].[PeriodEnd] AS [PeriodEnd1], [t1].[PeriodStart] AS [PeriodStart1], [t4].[Id] AS [Id2], [t4].[Level2_Optional_Id] AS [Level2_Optional_Id0], [t4].[Level2_Required_Id] AS [Level2_Required_Id0], [t4].[Level3_Name] AS [Level3_Name0], [t4].[OneToMany_Optional_Inverse3Id] AS [OneToMany_Optional_Inverse3Id0], [t4].[OneToMany_Required_Inverse3Id] AS [OneToMany_Required_Inverse3Id0], [t4].[OneToOne_Optional_PK_Inverse3Id] AS [OneToOne_Optional_PK_Inverse3Id0], [t4].[PeriodEnd] AS [PeriodEnd2], [t4].[PeriodStart] AS [PeriodStart2], [l1].[Id] AS [Id3], [t0].[Id0] AS [Id00], [t0].[Id00] AS [Id000], [t1].[Id0] AS [Id01], [t1].[Id00] AS [Id001], [t1].[Id000] AS [Id0000], [t4].[Id0] AS [Id02], [t4].[Id00] AS [Id002], [t6].[Id] AS [Id4], [t6].[Level3_Optional_Id] AS [Level3_Optional_Id0], [t6].[Level3_Required_Id] AS [Level3_Required_Id0], [t6].[Level4_Name] AS [Level4_Name0], [t6].[OneToMany_Optional_Inverse4Id] AS [OneToMany_Optional_Inverse4Id0], [t6].[OneToMany_Required_Inverse4Id] AS [OneToMany_Required_Inverse4Id0], [t6].[OneToOne_Optional_PK_Inverse4Id] AS [OneToOne_Optional_PK_Inverse4Id0], [t6].[PeriodEnd] AS [PeriodEnd3], [t6].[PeriodStart] AS [PeriodStart3], [t6].[Id0] AS [Id03], [t6].[Id00] AS [Id003], [t6].[Id000] AS [Id0001] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t].[Id] AS [Id0], [t].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] ON [l2].[Id] = [t].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t0] ON CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END = [t0].[OneToOne_Optional_PK_Inverse3Id] + LEFT JOIN ( + SELECT [l5].[Id], [l5].[Level3_Optional_Id], [l5].[Level3_Required_Id], [l5].[Level4_Name], [l5].[OneToMany_Optional_Inverse4Id], [l5].[OneToMany_Required_Inverse4Id], [l5].[OneToOne_Optional_PK_Inverse4Id], [l5].[PeriodEnd], [l5].[PeriodStart], [t2].[Id] AS [Id0], [t2].[Id0] AS [Id00], [t2].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN ( + SELECT [l6].[Id], [t3].[Id] AS [Id0], [t3].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] + INNER JOIN ( + SELECT [l7].[Id], [l8].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] ON [l7].[Id] = [l8].[Id] + WHERE [l7].[OneToOne_Required_PK_Date] IS NOT NULL AND [l7].[Level1_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t3] ON [l6].[Id] = [t3].[Id] + WHERE [l6].[Level2_Required_Id] IS NOT NULL AND [l6].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t2] ON [l5].[Id] = [t2].[Id] + WHERE [l5].[Level3_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse4Id] IS NOT NULL + ) AS [t1] ON CASE + WHEN [t0].[Level2_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse3Id] IS NOT NULL AND [t0].[PeriodEnd] IS NOT NULL AND [t0].[PeriodStart] IS NOT NULL THEN [t0].[Id] + END = [t1].[Level3_Optional_Id] + LEFT JOIN ( + SELECT [l9].[Id], [l9].[Level2_Optional_Id], [l9].[Level2_Required_Id], [l9].[Level3_Name], [l9].[OneToMany_Optional_Inverse3Id], [l9].[OneToMany_Required_Inverse3Id], [l9].[OneToOne_Optional_PK_Inverse3Id], [l9].[PeriodEnd], [l9].[PeriodStart], [t5].[Id] AS [Id0], [t5].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l9] + INNER JOIN ( + SELECT [l10].[Id], [l11].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l10] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l11] ON [l10].[Id] = [l11].[Id] + WHERE [l10].[OneToOne_Required_PK_Date] IS NOT NULL AND [l10].[Level1_Required_Id] IS NOT NULL AND [l10].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t5] ON [l9].[Id] = [t5].[Id] + WHERE [l9].[Level2_Required_Id] IS NOT NULL AND [l9].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t4] ON CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END = [t4].[Level2_Optional_Id] + LEFT JOIN ( + SELECT [l12].[Id], [l12].[Level3_Optional_Id], [l12].[Level3_Required_Id], [l12].[Level4_Name], [l12].[OneToMany_Optional_Inverse4Id], [l12].[OneToMany_Required_Inverse4Id], [l12].[OneToOne_Optional_PK_Inverse4Id], [l12].[PeriodEnd], [l12].[PeriodStart], [t7].[Id] AS [Id0], [t7].[Id0] AS [Id00], [t7].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l12] + INNER JOIN ( + SELECT [l13].[Id], [t8].[Id] AS [Id0], [t8].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l13] + INNER JOIN ( + SELECT [l14].[Id], [l15].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l14] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l15] ON [l14].[Id] = [l15].[Id] + WHERE [l14].[OneToOne_Required_PK_Date] IS NOT NULL AND [l14].[Level1_Required_Id] IS NOT NULL AND [l14].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t8] ON [l13].[Id] = [t8].[Id] + WHERE [l13].[Level2_Required_Id] IS NOT NULL AND [l13].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t7] ON [l12].[Id] = [t7].[Id] + WHERE [l12].[Level3_Required_Id] IS NOT NULL AND [l12].[OneToMany_Required_Inverse4Id] IS NOT NULL + ) AS [t6] ON CASE + WHEN [t4].[Level2_Required_Id] IS NOT NULL AND [t4].[OneToMany_Required_Inverse3Id] IS NOT NULL AND [t4].[PeriodEnd] IS NOT NULL AND [t4].[PeriodStart] IS NOT NULL THEN [t4].[Id] + END = [t6].[OneToMany_Optional_Inverse4Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t9] ON [l].[Id] = [t9].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t9].[Id], [t9].[Id3], [t9].[Id0], [t9].[Id00], [t9].[Id000], [t9].[Id1], [t9].[Id01], [t9].[Id001], [t9].[Id0000], [t9].[Id2], [t9].[Id02], [t9].[Id002], [t9].[Id4], [t9].[Id03], [t9].[Id003]"); + } + + public override async Task Include_collection_followed_by_include_reference(bool async) + { + await base.Include_collection_followed_by_include_reference(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t1].[Id], [t1].[OneToOne_Required_PK_Date], [t1].[Level1_Optional_Id], [t1].[Level1_Required_Id], [t1].[Level2_Name], [t1].[OneToMany_Optional_Inverse2Id], [t1].[OneToMany_Required_Inverse2Id], [t1].[OneToOne_Optional_PK_Inverse2Id], [t1].[PeriodEnd], [t1].[PeriodStart], [t1].[Id0], [t1].[Level2_Optional_Id], [t1].[Level2_Required_Id], [t1].[Level3_Name], [t1].[OneToMany_Optional_Inverse3Id], [t1].[OneToMany_Required_Inverse3Id], [t1].[OneToOne_Optional_PK_Inverse3Id], [t1].[PeriodEnd0], [t1].[PeriodStart0], [t1].[Id1], [t1].[Id00], [t1].[Id000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [t0].[Id] AS [Id0], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd] AS [PeriodEnd0], [t0].[PeriodStart] AS [PeriodStart0], [l1].[Id] AS [Id1], [t0].[Id0] AS [Id00], [t0].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t].[Id] AS [Id0], [t].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] ON [l2].[Id] = [t].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t0] ON CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END = [t0].[OneToOne_Optional_PK_Inverse3Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t1] ON [l].[Id] = [t1].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t1].[Id], [t1].[Id1], [t1].[Id0], [t1].[Id00]"); + } + + public override async Task Include_collection_followed_by_projecting_the_included_collection(bool async) + { + await base.Include_collection_followed_by_projecting_the_included_collection(async); + + AssertSql( + @"SELECT [l].[Id], [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t].[Id]"); + } + + public override async Task Include_collection_multiple(bool async) + { + await base.Include_collection_multiple(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t9].[Id], [t9].[OneToOne_Required_PK_Date], [t9].[Level1_Optional_Id], [t9].[Level1_Required_Id], [t9].[Level2_Name], [t9].[OneToMany_Optional_Inverse2Id], [t9].[OneToMany_Required_Inverse2Id], [t9].[OneToOne_Optional_PK_Inverse2Id], [t9].[PeriodEnd], [t9].[PeriodStart], [t9].[Id0], [t9].[Level2_Optional_Id], [t9].[Level2_Required_Id], [t9].[Level3_Name], [t9].[OneToMany_Optional_Inverse3Id], [t9].[OneToMany_Required_Inverse3Id], [t9].[OneToOne_Optional_PK_Inverse3Id], [t9].[PeriodEnd0], [t9].[PeriodStart0], [t9].[Id1], [t9].[Level3_Optional_Id], [t9].[Level3_Required_Id], [t9].[Level4_Name], [t9].[OneToMany_Optional_Inverse4Id], [t9].[OneToMany_Required_Inverse4Id], [t9].[OneToOne_Optional_PK_Inverse4Id], [t9].[PeriodEnd1], [t9].[PeriodStart1], [t9].[Id2], [t9].[Level2_Optional_Id0], [t9].[Level2_Required_Id0], [t9].[Level3_Name0], [t9].[OneToMany_Optional_Inverse3Id0], [t9].[OneToMany_Required_Inverse3Id0], [t9].[OneToOne_Optional_PK_Inverse3Id0], [t9].[PeriodEnd2], [t9].[PeriodStart2], [t9].[Id3], [t9].[Id00], [t9].[Id000], [t9].[Id01], [t9].[Id001], [t9].[Id0000], [t9].[Id02], [t9].[Id002], [t9].[Id4], [t9].[Level3_Optional_Id0], [t9].[Level3_Required_Id0], [t9].[Level4_Name0], [t9].[OneToMany_Optional_Inverse4Id0], [t9].[OneToMany_Required_Inverse4Id0], [t9].[OneToOne_Optional_PK_Inverse4Id0], [t9].[PeriodEnd3], [t9].[PeriodStart3], [t9].[Id03], [t9].[Id003], [t9].[Id0001] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [t0].[Id] AS [Id0], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd] AS [PeriodEnd0], [t0].[PeriodStart] AS [PeriodStart0], [t1].[Id] AS [Id1], [t1].[Level3_Optional_Id], [t1].[Level3_Required_Id], [t1].[Level4_Name], [t1].[OneToMany_Optional_Inverse4Id], [t1].[OneToMany_Required_Inverse4Id], [t1].[OneToOne_Optional_PK_Inverse4Id], [t1].[PeriodEnd] AS [PeriodEnd1], [t1].[PeriodStart] AS [PeriodStart1], [t4].[Id] AS [Id2], [t4].[Level2_Optional_Id] AS [Level2_Optional_Id0], [t4].[Level2_Required_Id] AS [Level2_Required_Id0], [t4].[Level3_Name] AS [Level3_Name0], [t4].[OneToMany_Optional_Inverse3Id] AS [OneToMany_Optional_Inverse3Id0], [t4].[OneToMany_Required_Inverse3Id] AS [OneToMany_Required_Inverse3Id0], [t4].[OneToOne_Optional_PK_Inverse3Id] AS [OneToOne_Optional_PK_Inverse3Id0], [t4].[PeriodEnd] AS [PeriodEnd2], [t4].[PeriodStart] AS [PeriodStart2], [l1].[Id] AS [Id3], [t0].[Id0] AS [Id00], [t0].[Id00] AS [Id000], [t1].[Id0] AS [Id01], [t1].[Id00] AS [Id001], [t1].[Id000] AS [Id0000], [t4].[Id0] AS [Id02], [t4].[Id00] AS [Id002], [t6].[Id] AS [Id4], [t6].[Level3_Optional_Id] AS [Level3_Optional_Id0], [t6].[Level3_Required_Id] AS [Level3_Required_Id0], [t6].[Level4_Name] AS [Level4_Name0], [t6].[OneToMany_Optional_Inverse4Id] AS [OneToMany_Optional_Inverse4Id0], [t6].[OneToMany_Required_Inverse4Id] AS [OneToMany_Required_Inverse4Id0], [t6].[OneToOne_Optional_PK_Inverse4Id] AS [OneToOne_Optional_PK_Inverse4Id0], [t6].[PeriodEnd] AS [PeriodEnd3], [t6].[PeriodStart] AS [PeriodStart3], [t6].[Id0] AS [Id03], [t6].[Id00] AS [Id003], [t6].[Id000] AS [Id0001] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t].[Id] AS [Id0], [t].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] ON [l2].[Id] = [t].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t0] ON CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END = [t0].[OneToOne_Optional_PK_Inverse3Id] + LEFT JOIN ( + SELECT [l5].[Id], [l5].[Level3_Optional_Id], [l5].[Level3_Required_Id], [l5].[Level4_Name], [l5].[OneToMany_Optional_Inverse4Id], [l5].[OneToMany_Required_Inverse4Id], [l5].[OneToOne_Optional_PK_Inverse4Id], [l5].[PeriodEnd], [l5].[PeriodStart], [t2].[Id] AS [Id0], [t2].[Id0] AS [Id00], [t2].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN ( + SELECT [l6].[Id], [t3].[Id] AS [Id0], [t3].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] + INNER JOIN ( + SELECT [l7].[Id], [l8].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] ON [l7].[Id] = [l8].[Id] + WHERE [l7].[OneToOne_Required_PK_Date] IS NOT NULL AND [l7].[Level1_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t3] ON [l6].[Id] = [t3].[Id] + WHERE [l6].[Level2_Required_Id] IS NOT NULL AND [l6].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t2] ON [l5].[Id] = [t2].[Id] + WHERE [l5].[Level3_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse4Id] IS NOT NULL + ) AS [t1] ON CASE + WHEN [t0].[Level2_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse3Id] IS NOT NULL AND [t0].[PeriodEnd] IS NOT NULL AND [t0].[PeriodStart] IS NOT NULL THEN [t0].[Id] + END = [t1].[Level3_Optional_Id] + LEFT JOIN ( + SELECT [l9].[Id], [l9].[Level2_Optional_Id], [l9].[Level2_Required_Id], [l9].[Level3_Name], [l9].[OneToMany_Optional_Inverse3Id], [l9].[OneToMany_Required_Inverse3Id], [l9].[OneToOne_Optional_PK_Inverse3Id], [l9].[PeriodEnd], [l9].[PeriodStart], [t5].[Id] AS [Id0], [t5].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l9] + INNER JOIN ( + SELECT [l10].[Id], [l11].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l10] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l11] ON [l10].[Id] = [l11].[Id] + WHERE [l10].[OneToOne_Required_PK_Date] IS NOT NULL AND [l10].[Level1_Required_Id] IS NOT NULL AND [l10].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t5] ON [l9].[Id] = [t5].[Id] + WHERE [l9].[Level2_Required_Id] IS NOT NULL AND [l9].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t4] ON CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END = [t4].[Level2_Optional_Id] + LEFT JOIN ( + SELECT [l12].[Id], [l12].[Level3_Optional_Id], [l12].[Level3_Required_Id], [l12].[Level4_Name], [l12].[OneToMany_Optional_Inverse4Id], [l12].[OneToMany_Required_Inverse4Id], [l12].[OneToOne_Optional_PK_Inverse4Id], [l12].[PeriodEnd], [l12].[PeriodStart], [t7].[Id] AS [Id0], [t7].[Id0] AS [Id00], [t7].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l12] + INNER JOIN ( + SELECT [l13].[Id], [t8].[Id] AS [Id0], [t8].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l13] + INNER JOIN ( + SELECT [l14].[Id], [l15].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l14] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l15] ON [l14].[Id] = [l15].[Id] + WHERE [l14].[OneToOne_Required_PK_Date] IS NOT NULL AND [l14].[Level1_Required_Id] IS NOT NULL AND [l14].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t8] ON [l13].[Id] = [t8].[Id] + WHERE [l13].[Level2_Required_Id] IS NOT NULL AND [l13].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t7] ON [l12].[Id] = [t7].[Id] + WHERE [l12].[Level3_Required_Id] IS NOT NULL AND [l12].[OneToMany_Required_Inverse4Id] IS NOT NULL + ) AS [t6] ON CASE + WHEN [t4].[Level2_Required_Id] IS NOT NULL AND [t4].[OneToMany_Required_Inverse3Id] IS NOT NULL AND [t4].[PeriodEnd] IS NOT NULL AND [t4].[PeriodStart] IS NOT NULL THEN [t4].[Id] + END = [t6].[OneToMany_Optional_Inverse4Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t9] ON [l].[Id] = [t9].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t9].[Id], [t9].[Id3], [t9].[Id0], [t9].[Id00], [t9].[Id000], [t9].[Id1], [t9].[Id01], [t9].[Id001], [t9].[Id0000], [t9].[Id2], [t9].[Id02], [t9].[Id002], [t9].[Id4], [t9].[Id03], [t9].[Id003]"); + } + + public override async Task Include_collection_multiple_with_filter(bool async) + { + await base.Include_collection_multiple_with_filter(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t4].[Id], [t4].[OneToOne_Required_PK_Date], [t4].[Level1_Optional_Id], [t4].[Level1_Required_Id], [t4].[Level2_Name], [t4].[OneToMany_Optional_Inverse2Id], [t4].[OneToMany_Required_Inverse2Id], [t4].[OneToOne_Optional_PK_Inverse2Id], [t4].[PeriodEnd], [t4].[PeriodStart], [t4].[Id0], [t4].[Level2_Optional_Id], [t4].[Level2_Required_Id], [t4].[Level3_Name], [t4].[OneToMany_Optional_Inverse3Id], [t4].[OneToMany_Required_Inverse3Id], [t4].[OneToOne_Optional_PK_Inverse3Id], [t4].[PeriodEnd0], [t4].[PeriodStart0], [t4].[Id1], [t4].[Level3_Optional_Id], [t4].[Level3_Required_Id], [t4].[Level4_Name], [t4].[OneToMany_Optional_Inverse4Id], [t4].[OneToMany_Required_Inverse4Id], [t4].[OneToOne_Optional_PK_Inverse4Id], [t4].[PeriodEnd1], [t4].[PeriodStart1], [t4].[Id2], [t4].[Id00], [t4].[Id000], [t4].[Id01], [t4].[Id001], [t4].[Id0000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l5].[Id], [l5].[OneToOne_Required_PK_Date], [l5].[Level1_Optional_Id], [l5].[Level1_Required_Id], [l5].[Level2_Name], [l5].[OneToMany_Optional_Inverse2Id], [l5].[OneToMany_Required_Inverse2Id], [l5].[OneToOne_Optional_PK_Inverse2Id], [l5].[PeriodEnd], [l5].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Level2_Optional_Id], [t1].[Level2_Required_Id], [t1].[Level3_Name], [t1].[OneToMany_Optional_Inverse3Id], [t1].[OneToMany_Required_Inverse3Id], [t1].[OneToOne_Optional_PK_Inverse3Id], [t1].[PeriodEnd] AS [PeriodEnd0], [t1].[PeriodStart] AS [PeriodStart0], [t2].[Id] AS [Id1], [t2].[Level3_Optional_Id], [t2].[Level3_Required_Id], [t2].[Level4_Name], [t2].[OneToMany_Optional_Inverse4Id], [t2].[OneToMany_Required_Inverse4Id], [t2].[OneToOne_Optional_PK_Inverse4Id], [t2].[PeriodEnd] AS [PeriodEnd1], [t2].[PeriodStart] AS [PeriodStart1], [l6].[Id] AS [Id2], [t1].[Id0] AS [Id00], [t1].[Id00] AS [Id000], [t2].[Id0] AS [Id01], [t2].[Id00] AS [Id001], [t2].[Id000] AS [Id0000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] ON [l5].[Id] = [l6].[Id] + LEFT JOIN ( + SELECT [l7].[Id], [l7].[Level2_Optional_Id], [l7].[Level2_Required_Id], [l7].[Level3_Name], [l7].[OneToMany_Optional_Inverse3Id], [l7].[OneToMany_Required_Inverse3Id], [l7].[OneToOne_Optional_PK_Inverse3Id], [l7].[PeriodEnd], [l7].[PeriodStart], [t3].[Id] AS [Id0], [t3].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] + INNER JOIN ( + SELECT [l8].[Id], [l9].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l9] ON [l8].[Id] = [l9].[Id] + WHERE [l8].[OneToOne_Required_PK_Date] IS NOT NULL AND [l8].[Level1_Required_Id] IS NOT NULL AND [l8].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t3] ON [l7].[Id] = [t3].[Id] + WHERE [l7].[Level2_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t1] ON CASE + WHEN [l5].[OneToOne_Required_PK_Date] IS NOT NULL AND [l5].[Level1_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l5].[Id] + END = [t1].[OneToOne_Optional_PK_Inverse3Id] + LEFT JOIN ( + SELECT [l10].[Id], [l10].[Level3_Optional_Id], [l10].[Level3_Required_Id], [l10].[Level4_Name], [l10].[OneToMany_Optional_Inverse4Id], [l10].[OneToMany_Required_Inverse4Id], [l10].[OneToOne_Optional_PK_Inverse4Id], [l10].[PeriodEnd], [l10].[PeriodStart], [t5].[Id] AS [Id0], [t5].[Id0] AS [Id00], [t5].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l10] + INNER JOIN ( + SELECT [l11].[Id], [t6].[Id] AS [Id0], [t6].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l11] + INNER JOIN ( + SELECT [l12].[Id], [l13].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l12] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l13] ON [l12].[Id] = [l13].[Id] + WHERE [l12].[OneToOne_Required_PK_Date] IS NOT NULL AND [l12].[Level1_Required_Id] IS NOT NULL AND [l12].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t6] ON [l11].[Id] = [t6].[Id] + WHERE [l11].[Level2_Required_Id] IS NOT NULL AND [l11].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t5] ON [l10].[Id] = [t5].[Id] + WHERE [l10].[Level3_Required_Id] IS NOT NULL AND [l10].[OneToMany_Required_Inverse4Id] IS NOT NULL + ) AS [t2] ON CASE + WHEN [t1].[Level2_Required_Id] IS NOT NULL AND [t1].[OneToMany_Required_Inverse3Id] IS NOT NULL AND [t1].[PeriodEnd] IS NOT NULL AND [t1].[PeriodStart] IS NOT NULL THEN [t1].[Id] + END = [t2].[Level3_Optional_Id] + WHERE [l5].[OneToOne_Required_PK_Date] IS NOT NULL AND [l5].[Level1_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t4] ON [l].[Id] = [t4].[OneToMany_Optional_Inverse2Id] +WHERE ( + SELECT COUNT(*) + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t].[Id] AS [Id0], [t].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l3].[OneToOne_Required_PK_Date], [l3].[Level1_Optional_Id], [l3].[Level1_Required_Id], [l3].[Level2_Name], [l3].[OneToMany_Optional_Inverse2Id], [l3].[OneToMany_Required_Inverse2Id], [l3].[OneToOne_Optional_PK_Inverse2Id], [l3].[PeriodEnd], [l3].[PeriodStart], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] ON [l2].[Id] = [t].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t0] ON CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END = [t0].[OneToOne_Optional_PK_Inverse3Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [l].[Id] = [l0].[OneToMany_Optional_Inverse2Id] AND ([t0].[Level3_Name] <> N'Foo' OR [t0].[Level3_Name] IS NULL)) > 0 +ORDER BY [l].[Id], [t4].[Id], [t4].[Id2], [t4].[Id0], [t4].[Id00], [t4].[Id000], [t4].[Id1], [t4].[Id01], [t4].[Id001]"); + } + + public override async Task Include_collection_ThenInclude_reference_followed_by_projection_into_anonmous_type(bool async) + { + await base.Include_collection_ThenInclude_reference_followed_by_projection_into_anonmous_type(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t1].[Id], [t1].[OneToOne_Required_PK_Date], [t1].[Level1_Optional_Id], [t1].[Level1_Required_Id], [t1].[Level2_Name], [t1].[OneToMany_Optional_Inverse2Id], [t1].[OneToMany_Required_Inverse2Id], [t1].[OneToOne_Optional_PK_Inverse2Id], [t1].[PeriodEnd], [t1].[PeriodStart], [t1].[Id0], [t1].[Level2_Optional_Id], [t1].[Level2_Required_Id], [t1].[Level3_Name], [t1].[OneToMany_Optional_Inverse3Id], [t1].[OneToMany_Required_Inverse3Id], [t1].[OneToOne_Optional_PK_Inverse3Id], [t1].[PeriodEnd0], [t1].[PeriodStart0], [t1].[Id1], [t1].[Id00], [t1].[Id000], [t2].[Id], [t2].[OneToOne_Required_PK_Date], [t2].[Level1_Optional_Id], [t2].[Level1_Required_Id], [t2].[Level2_Name], [t2].[OneToMany_Optional_Inverse2Id], [t2].[OneToMany_Required_Inverse2Id], [t2].[OneToOne_Optional_PK_Inverse2Id], [t2].[PeriodEnd], [t2].[PeriodStart], [t2].[Id0], [t2].[Level2_Optional_Id], [t2].[Level2_Required_Id], [t2].[Level3_Name], [t2].[OneToMany_Optional_Inverse3Id], [t2].[OneToMany_Required_Inverse3Id], [t2].[OneToOne_Optional_PK_Inverse3Id], [t2].[PeriodEnd0], [t2].[PeriodStart0], [t2].[Id1], [t2].[Id00], [t2].[Id000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [t0].[Id] AS [Id0], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd] AS [PeriodEnd0], [t0].[PeriodStart] AS [PeriodStart0], [l1].[Id] AS [Id1], [t0].[Id0] AS [Id00], [t0].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t].[Id] AS [Id0], [t].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] ON [l2].[Id] = [t].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t0] ON CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END = [t0].[OneToOne_Optional_PK_Inverse3Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t1] ON [l].[Id] = [t1].[OneToMany_Optional_Inverse2Id] +LEFT JOIN ( + SELECT [l5].[Id], [l5].[OneToOne_Required_PK_Date], [l5].[Level1_Optional_Id], [l5].[Level1_Required_Id], [l5].[Level2_Name], [l5].[OneToMany_Optional_Inverse2Id], [l5].[OneToMany_Required_Inverse2Id], [l5].[OneToOne_Optional_PK_Inverse2Id], [l5].[PeriodEnd], [l5].[PeriodStart], [t3].[Id] AS [Id0], [t3].[Level2_Optional_Id], [t3].[Level2_Required_Id], [t3].[Level3_Name], [t3].[OneToMany_Optional_Inverse3Id], [t3].[OneToMany_Required_Inverse3Id], [t3].[OneToOne_Optional_PK_Inverse3Id], [t3].[PeriodEnd] AS [PeriodEnd0], [t3].[PeriodStart] AS [PeriodStart0], [l6].[Id] AS [Id1], [t3].[Id0] AS [Id00], [t3].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] ON [l5].[Id] = [l6].[Id] + LEFT JOIN ( + SELECT [l7].[Id], [l7].[Level2_Optional_Id], [l7].[Level2_Required_Id], [l7].[Level3_Name], [l7].[OneToMany_Optional_Inverse3Id], [l7].[OneToMany_Required_Inverse3Id], [l7].[OneToOne_Optional_PK_Inverse3Id], [l7].[PeriodEnd], [l7].[PeriodStart], [t4].[Id] AS [Id0], [t4].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] + INNER JOIN ( + SELECT [l8].[Id], [l9].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l9] ON [l8].[Id] = [l9].[Id] + WHERE [l8].[OneToOne_Required_PK_Date] IS NOT NULL AND [l8].[Level1_Required_Id] IS NOT NULL AND [l8].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t4] ON [l7].[Id] = [t4].[Id] + WHERE [l7].[Level2_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t3] ON CASE + WHEN [l5].[OneToOne_Required_PK_Date] IS NOT NULL AND [l5].[Level1_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l5].[Id] + END = [t3].[OneToOne_Optional_PK_Inverse3Id] + WHERE [l5].[OneToOne_Required_PK_Date] IS NOT NULL AND [l5].[Level1_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t2] ON [l].[Id] = [t2].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t1].[Id], [t1].[Id1], [t1].[Id0], [t1].[Id00], [t1].[Id000], [t2].[Id], [t2].[Id1], [t2].[Id0], [t2].[Id00]"); + } + + public override async Task Include_collection_ThenInclude_two_references(bool async) + { + await base.Include_collection_ThenInclude_two_references(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t4].[Id], [t4].[OneToOne_Required_PK_Date], [t4].[Level1_Optional_Id], [t4].[Level1_Required_Id], [t4].[Level2_Name], [t4].[OneToMany_Optional_Inverse2Id], [t4].[OneToMany_Required_Inverse2Id], [t4].[OneToOne_Optional_PK_Inverse2Id], [t4].[PeriodEnd], [t4].[PeriodStart], [t4].[Id0], [t4].[Level2_Optional_Id], [t4].[Level2_Required_Id], [t4].[Level3_Name], [t4].[OneToMany_Optional_Inverse3Id], [t4].[OneToMany_Required_Inverse3Id], [t4].[OneToOne_Optional_PK_Inverse3Id], [t4].[PeriodEnd0], [t4].[PeriodStart0], [t4].[Id1], [t4].[Level3_Optional_Id], [t4].[Level3_Required_Id], [t4].[Level4_Name], [t4].[OneToMany_Optional_Inverse4Id], [t4].[OneToMany_Required_Inverse4Id], [t4].[OneToOne_Optional_PK_Inverse4Id], [t4].[PeriodEnd1], [t4].[PeriodStart1], [t4].[Id2], [t4].[Id00], [t4].[Id000], [t4].[Id01], [t4].[Id001], [t4].[Id0000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [t0].[Id] AS [Id0], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd] AS [PeriodEnd0], [t0].[PeriodStart] AS [PeriodStart0], [t1].[Id] AS [Id1], [t1].[Level3_Optional_Id], [t1].[Level3_Required_Id], [t1].[Level4_Name], [t1].[OneToMany_Optional_Inverse4Id], [t1].[OneToMany_Required_Inverse4Id], [t1].[OneToOne_Optional_PK_Inverse4Id], [t1].[PeriodEnd] AS [PeriodEnd1], [t1].[PeriodStart] AS [PeriodStart1], [l1].[Id] AS [Id2], [t0].[Id0] AS [Id00], [t0].[Id00] AS [Id000], [t1].[Id0] AS [Id01], [t1].[Id00] AS [Id001], [t1].[Id000] AS [Id0000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t].[Id] AS [Id0], [t].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] ON [l2].[Id] = [t].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t0] ON CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END = [t0].[OneToOne_Optional_PK_Inverse3Id] + LEFT JOIN ( + SELECT [l5].[Id], [l5].[Level3_Optional_Id], [l5].[Level3_Required_Id], [l5].[Level4_Name], [l5].[OneToMany_Optional_Inverse4Id], [l5].[OneToMany_Required_Inverse4Id], [l5].[OneToOne_Optional_PK_Inverse4Id], [l5].[PeriodEnd], [l5].[PeriodStart], [t2].[Id] AS [Id0], [t2].[Id0] AS [Id00], [t2].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN ( + SELECT [l6].[Id], [t3].[Id] AS [Id0], [t3].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] + INNER JOIN ( + SELECT [l7].[Id], [l8].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] ON [l7].[Id] = [l8].[Id] + WHERE [l7].[OneToOne_Required_PK_Date] IS NOT NULL AND [l7].[Level1_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t3] ON [l6].[Id] = [t3].[Id] + WHERE [l6].[Level2_Required_Id] IS NOT NULL AND [l6].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t2] ON [l5].[Id] = [t2].[Id] + WHERE [l5].[Level3_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse4Id] IS NOT NULL + ) AS [t1] ON CASE + WHEN [t0].[Level2_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse3Id] IS NOT NULL AND [t0].[PeriodEnd] IS NOT NULL AND [t0].[PeriodStart] IS NOT NULL THEN [t0].[Id] + END = [t1].[Level3_Optional_Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t4] ON [l].[Id] = [t4].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t4].[Id], [t4].[Id2], [t4].[Id0], [t4].[Id00], [t4].[Id000], [t4].[Id1], [t4].[Id01], [t4].[Id001]"); + } + + public override async Task Include_collection_then_reference(bool async) + { + await base.Include_collection_then_reference(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t1].[Id], [t1].[OneToOne_Required_PK_Date], [t1].[Level1_Optional_Id], [t1].[Level1_Required_Id], [t1].[Level2_Name], [t1].[OneToMany_Optional_Inverse2Id], [t1].[OneToMany_Required_Inverse2Id], [t1].[OneToOne_Optional_PK_Inverse2Id], [t1].[PeriodEnd], [t1].[PeriodStart], [t1].[Id0], [t1].[Level2_Optional_Id], [t1].[Level2_Required_Id], [t1].[Level3_Name], [t1].[OneToMany_Optional_Inverse3Id], [t1].[OneToMany_Required_Inverse3Id], [t1].[OneToOne_Optional_PK_Inverse3Id], [t1].[PeriodEnd0], [t1].[PeriodStart0], [t1].[Id1], [t1].[Id00], [t1].[Id000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [t0].[Id] AS [Id0], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd] AS [PeriodEnd0], [t0].[PeriodStart] AS [PeriodStart0], [l1].[Id] AS [Id1], [t0].[Id0] AS [Id00], [t0].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t].[Id] AS [Id0], [t].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] ON [l2].[Id] = [t].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t0] ON CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END = [t0].[Level2_Optional_Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t1] ON [l].[Id] = [t1].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t1].[Id], [t1].[Id1], [t1].[Id0], [t1].[Id00]"); + } + + public override async Task Include_collection_with_conditional_order_by(bool async) + { + await base.Include_collection_with_conditional_order_by(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[OneToMany_Optional_Inverse2Id] +ORDER BY CASE + WHEN [l].[Name] IS NOT NULL AND ([l].[Name] LIKE N'%03') THEN 1 + ELSE 2 +END, [l].[Id], [t].[Id]"); + } + + public override async Task Include_collection_with_groupby_in_subquery(bool async) + { + await base.Include_collection_with_groupby_in_subquery(async); + + AssertSql( + @"SELECT [t0].[Id], [t0].[Date], [t0].[Name], [t0].[PeriodEnd], [t0].[PeriodStart], [t].[Name], [t2].[Id], [t2].[OneToOne_Required_PK_Date], [t2].[Level1_Optional_Id], [t2].[Level1_Required_Id], [t2].[Level2_Name], [t2].[OneToMany_Optional_Inverse2Id], [t2].[OneToMany_Required_Inverse2Id], [t2].[OneToOne_Optional_PK_Inverse2Id], [t2].[PeriodEnd], [t2].[PeriodStart], [t2].[Id0] +FROM ( + SELECT [l].[Name] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] + GROUP BY [l].[Name] +) AS [t] +LEFT JOIN ( + SELECT [t1].[Id], [t1].[Date], [t1].[Name], [t1].[PeriodEnd], [t1].[PeriodStart] + FROM ( + SELECT [l0].[Id], [l0].[Date], [l0].[Name], [l0].[PeriodEnd], [l0].[PeriodStart], ROW_NUMBER() OVER(PARTITION BY [l0].[Name] ORDER BY [l0].[Id]) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + ) AS [t1] + WHERE [t1].[row] <= 1 +) AS [t0] ON [t].[Name] = [t0].[Name] +LEFT JOIN ( + SELECT [l1].[Id], [l1].[OneToOne_Required_PK_Date], [l1].[Level1_Optional_Id], [l1].[Level1_Required_Id], [l1].[Level2_Name], [l1].[OneToMany_Optional_Inverse2Id], [l1].[OneToMany_Required_Inverse2Id], [l1].[OneToOne_Optional_PK_Inverse2Id], [l1].[PeriodEnd], [l1].[PeriodStart], [l2].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] ON [l1].[Id] = [l2].[Id] + WHERE [l1].[OneToOne_Required_PK_Date] IS NOT NULL AND [l1].[Level1_Required_Id] IS NOT NULL AND [l1].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t2] ON [t0].[Id] = [t2].[OneToMany_Optional_Inverse2Id] +ORDER BY [t].[Name], [t0].[Id], [t2].[Id]"); + } + + public override async Task Include_collection_with_groupby_in_subquery_and_filter_after_groupby(bool async) + { + await base.Include_collection_with_groupby_in_subquery_and_filter_after_groupby(async); + + AssertSql( + @"SELECT [t0].[Id], [t0].[Date], [t0].[Name], [t0].[PeriodEnd], [t0].[PeriodStart], [t].[Name], [t2].[Id], [t2].[OneToOne_Required_PK_Date], [t2].[Level1_Optional_Id], [t2].[Level1_Required_Id], [t2].[Level2_Name], [t2].[OneToMany_Optional_Inverse2Id], [t2].[OneToMany_Required_Inverse2Id], [t2].[OneToOne_Optional_PK_Inverse2Id], [t2].[PeriodEnd], [t2].[PeriodStart], [t2].[Id0] +FROM ( + SELECT [l].[Name] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] + GROUP BY [l].[Name] + HAVING [l].[Name] <> N'Foo' OR [l].[Name] IS NULL +) AS [t] +LEFT JOIN ( + SELECT [t1].[Id], [t1].[Date], [t1].[Name], [t1].[PeriodEnd], [t1].[PeriodStart] + FROM ( + SELECT [l0].[Id], [l0].[Date], [l0].[Name], [l0].[PeriodEnd], [l0].[PeriodStart], ROW_NUMBER() OVER(PARTITION BY [l0].[Name] ORDER BY [l0].[Id]) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + ) AS [t1] + WHERE [t1].[row] <= 1 +) AS [t0] ON [t].[Name] = [t0].[Name] +LEFT JOIN ( + SELECT [l1].[Id], [l1].[OneToOne_Required_PK_Date], [l1].[Level1_Optional_Id], [l1].[Level1_Required_Id], [l1].[Level2_Name], [l1].[OneToMany_Optional_Inverse2Id], [l1].[OneToMany_Required_Inverse2Id], [l1].[OneToOne_Optional_PK_Inverse2Id], [l1].[PeriodEnd], [l1].[PeriodStart], [l2].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] ON [l1].[Id] = [l2].[Id] + WHERE [l1].[OneToOne_Required_PK_Date] IS NOT NULL AND [l1].[Level1_Required_Id] IS NOT NULL AND [l1].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t2] ON [t0].[Id] = [t2].[OneToMany_Optional_Inverse2Id] +ORDER BY [t].[Name], [t0].[Id], [t2].[Id]"); + } + + public override async Task Include_collection_with_groupby_in_subquery_and_filter_before_groupby(bool async) + { + await base.Include_collection_with_groupby_in_subquery_and_filter_before_groupby(async); + + AssertSql( + @"SELECT [t0].[Id], [t0].[Date], [t0].[Name], [t0].[PeriodEnd], [t0].[PeriodStart], [t].[Name], [t2].[Id], [t2].[OneToOne_Required_PK_Date], [t2].[Level1_Optional_Id], [t2].[Level1_Required_Id], [t2].[Level2_Name], [t2].[OneToMany_Optional_Inverse2Id], [t2].[OneToMany_Required_Inverse2Id], [t2].[OneToOne_Optional_PK_Inverse2Id], [t2].[PeriodEnd], [t2].[PeriodStart], [t2].[Id0] +FROM ( + SELECT [l].[Name] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] + WHERE [l].[Id] > 3 + GROUP BY [l].[Name] +) AS [t] +LEFT JOIN ( + SELECT [t1].[Id], [t1].[Date], [t1].[Name], [t1].[PeriodEnd], [t1].[PeriodStart] + FROM ( + SELECT [l0].[Id], [l0].[Date], [l0].[Name], [l0].[PeriodEnd], [l0].[PeriodStart], ROW_NUMBER() OVER(PARTITION BY [l0].[Name] ORDER BY [l0].[Id]) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + WHERE [l0].[Id] > 3 + ) AS [t1] + WHERE [t1].[row] <= 1 +) AS [t0] ON [t].[Name] = [t0].[Name] +LEFT JOIN ( + SELECT [l1].[Id], [l1].[OneToOne_Required_PK_Date], [l1].[Level1_Optional_Id], [l1].[Level1_Required_Id], [l1].[Level2_Name], [l1].[OneToMany_Optional_Inverse2Id], [l1].[OneToMany_Required_Inverse2Id], [l1].[OneToOne_Optional_PK_Inverse2Id], [l1].[PeriodEnd], [l1].[PeriodStart], [l2].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] ON [l1].[Id] = [l2].[Id] + WHERE [l1].[OneToOne_Required_PK_Date] IS NOT NULL AND [l1].[Level1_Required_Id] IS NOT NULL AND [l1].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t2] ON [t0].[Id] = [t2].[OneToMany_Optional_Inverse2Id] +ORDER BY [t].[Name], [t0].[Id], [t2].[Id]"); + } + + public override async Task Include_nested_with_optional_navigation(bool async) + { + await base.Include_nested_with_optional_navigation(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0], [t3].[Id], [t3].[Level2_Optional_Id], [t3].[Level2_Required_Id], [t3].[Level3_Name], [t3].[OneToMany_Optional_Inverse3Id], [t3].[OneToMany_Required_Inverse3Id], [t3].[OneToOne_Optional_PK_Inverse3Id], [t3].[PeriodEnd], [t3].[PeriodStart], [t3].[Id0], [t3].[Level3_Optional_Id], [t3].[Level3_Required_Id], [t3].[Level4_Name], [t3].[OneToMany_Optional_Inverse4Id], [t3].[OneToMany_Required_Inverse4Id], [t3].[OneToOne_Optional_PK_Inverse4Id], [t3].[PeriodEnd0], [t3].[PeriodStart0], [t3].[Id1], [t3].[Id00], [t3].[Id01], [t3].[Id000], [t3].[Id0000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[Level1_Optional_Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Level3_Optional_Id], [t1].[Level3_Required_Id], [t1].[Level4_Name], [t1].[OneToMany_Optional_Inverse4Id], [t1].[OneToMany_Required_Inverse4Id], [t1].[OneToOne_Optional_PK_Inverse4Id], [t1].[PeriodEnd] AS [PeriodEnd0], [t1].[PeriodStart] AS [PeriodStart0], [t0].[Id] AS [Id1], [t0].[Id0] AS [Id00], [t1].[Id0] AS [Id01], [t1].[Id00] AS [Id000], [t1].[Id000] AS [Id0000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t0] ON [l2].[Id] = [t0].[Id] + LEFT JOIN ( + SELECT [l5].[Id], [l5].[Level3_Optional_Id], [l5].[Level3_Required_Id], [l5].[Level4_Name], [l5].[OneToMany_Optional_Inverse4Id], [l5].[OneToMany_Required_Inverse4Id], [l5].[OneToOne_Optional_PK_Inverse4Id], [l5].[PeriodEnd], [l5].[PeriodStart], [t2].[Id] AS [Id0], [t2].[Id0] AS [Id00], [t2].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN ( + SELECT [l6].[Id], [t4].[Id] AS [Id0], [t4].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] + INNER JOIN ( + SELECT [l7].[Id], [l8].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] ON [l7].[Id] = [l8].[Id] + WHERE [l7].[OneToOne_Required_PK_Date] IS NOT NULL AND [l7].[Level1_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t4] ON [l6].[Id] = [t4].[Id] + WHERE [l6].[Level2_Required_Id] IS NOT NULL AND [l6].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t2] ON [l5].[Id] = [t2].[Id] + WHERE [l5].[Level3_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse4Id] IS NOT NULL + ) AS [t1] ON CASE + WHEN [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [l2].[Id] + END = [t1].[Level3_Required_Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t3] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END = [t3].[OneToMany_Required_Inverse3Id] +WHERE [t].[Level2_Name] <> N'L2 09' OR [t].[Level2_Name] IS NULL +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t3].[Id], [t3].[Id1], [t3].[Id00], [t3].[Id0], [t3].[Id01], [t3].[Id000]"); + } + + public override async Task Include_partially_added_before_Where_and_then_build_upon(bool async) + { + await base.Include_partially_added_before_Where_and_then_build_upon(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t].[Id], [t].[Id0], [t0].[Id0], [t3].[Id], [t3].[Level2_Optional_Id], [t3].[Level2_Required_Id], [t3].[Level3_Name], [t3].[OneToMany_Optional_Inverse3Id], [t3].[OneToMany_Required_Inverse3Id], [t3].[OneToOne_Optional_PK_Inverse3Id], [t3].[PeriodEnd], [t3].[PeriodStart], [t3].[Id0], [t3].[Level3_Optional_Id], [t3].[Level3_Required_Id], [t3].[Level4_Name], [t3].[OneToMany_Optional_Inverse4Id], [t3].[OneToMany_Required_Inverse4Id], [t3].[OneToOne_Optional_PK_Inverse4Id], [t3].[PeriodEnd0], [t3].[PeriodStart0], [t3].[Id1], [t3].[Id00], [t3].[Id01], [t3].[Id000], [t3].[Id0000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Required_Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[OneToOne_Optional_PK_Inverse2Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[OneToOne_Required_PK_Date], [l2].[Level1_Optional_Id], [l2].[Level1_Required_Id], [l2].[Level2_Name], [l2].[OneToMany_Optional_Inverse2Id], [l2].[OneToMany_Required_Inverse2Id], [l2].[OneToOne_Optional_PK_Inverse2Id], [l2].[PeriodEnd], [l2].[PeriodStart], [l3].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] ON [l2].[Id] = [l3].[Id] + WHERE [l2].[OneToOne_Required_PK_Date] IS NOT NULL AND [l2].[Level1_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t0] ON [l].[Id] = [t0].[Level1_Optional_Id] +LEFT JOIN ( + SELECT [l4].[Id], [l4].[Level2_Optional_Id], [l4].[Level2_Required_Id], [l4].[Level3_Name], [l4].[OneToMany_Optional_Inverse3Id], [l4].[OneToMany_Required_Inverse3Id], [l4].[OneToOne_Optional_PK_Inverse3Id], [l4].[PeriodEnd], [l4].[PeriodStart], [t2].[Id] AS [Id0], [t2].[Level3_Optional_Id], [t2].[Level3_Required_Id], [t2].[Level4_Name], [t2].[OneToMany_Optional_Inverse4Id], [t2].[OneToMany_Required_Inverse4Id], [t2].[OneToOne_Optional_PK_Inverse4Id], [t2].[PeriodEnd] AS [PeriodEnd0], [t2].[PeriodStart] AS [PeriodStart0], [t1].[Id] AS [Id1], [t1].[Id0] AS [Id00], [t2].[Id0] AS [Id01], [t2].[Id00] AS [Id000], [t2].[Id000] AS [Id0000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] + INNER JOIN ( + SELECT [l5].[Id], [l6].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] ON [l5].[Id] = [l6].[Id] + WHERE [l5].[OneToOne_Required_PK_Date] IS NOT NULL AND [l5].[Level1_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l4].[Id] = [t1].[Id] + LEFT JOIN ( + SELECT [l7].[Id], [l7].[Level3_Optional_Id], [l7].[Level3_Required_Id], [l7].[Level4_Name], [l7].[OneToMany_Optional_Inverse4Id], [l7].[OneToMany_Required_Inverse4Id], [l7].[OneToOne_Optional_PK_Inverse4Id], [l7].[PeriodEnd], [l7].[PeriodStart], [t4].[Id] AS [Id0], [t4].[Id0] AS [Id00], [t4].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] + INNER JOIN ( + SELECT [l8].[Id], [t5].[Id] AS [Id0], [t5].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] + INNER JOIN ( + SELECT [l9].[Id], [l10].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l9] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l10] ON [l9].[Id] = [l10].[Id] + WHERE [l9].[OneToOne_Required_PK_Date] IS NOT NULL AND [l9].[Level1_Required_Id] IS NOT NULL AND [l9].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t5] ON [l8].[Id] = [t5].[Id] + WHERE [l8].[Level2_Required_Id] IS NOT NULL AND [l8].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t4] ON [l7].[Id] = [t4].[Id] + WHERE [l7].[Level3_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse4Id] IS NOT NULL + ) AS [t2] ON CASE + WHEN [l4].[Level2_Required_Id] IS NOT NULL AND [l4].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [l4].[Id] + END = [t2].[Level3_Optional_Id] + WHERE [l4].[Level2_Required_Id] IS NOT NULL AND [l4].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t3] ON CASE + WHEN [t0].[OneToOne_Required_PK_Date] IS NOT NULL AND [t0].[Level1_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t0].[PeriodEnd] IS NOT NULL AND [t0].[PeriodStart] IS NOT NULL THEN [t0].[Id] +END = [t3].[OneToMany_Optional_Inverse3Id] +WHERE CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END < 3 OR CASE + WHEN [t0].[OneToOne_Required_PK_Date] IS NOT NULL AND [t0].[Level1_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t0].[PeriodEnd] IS NOT NULL AND [t0].[PeriodStart] IS NOT NULL THEN [t0].[Id] +END > 8 +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0], [t3].[Id], [t3].[Id1], [t3].[Id00], [t3].[Id0], [t3].[Id01], [t3].[Id000]"); + } + + public override async Task Include_partially_added_before_Where_and_then_build_upon_with_filtered_include(bool async) + { + await base.Include_partially_added_before_Where_and_then_build_upon_with_filtered_include(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t].[Id], [t].[Id0], [t0].[Id0], [t1].[Id], [t1].[Level2_Optional_Id], [t1].[Level2_Required_Id], [t1].[Level3_Name], [t1].[OneToMany_Optional_Inverse3Id], [t1].[OneToMany_Required_Inverse3Id], [t1].[OneToOne_Optional_PK_Inverse3Id], [t1].[PeriodEnd], [t1].[PeriodStart], [t1].[Id0], [t1].[Id00], [t4].[Id], [t4].[Level2_Optional_Id], [t4].[Level2_Required_Id], [t4].[Level3_Name], [t4].[OneToMany_Optional_Inverse3Id], [t4].[OneToMany_Required_Inverse3Id], [t4].[OneToOne_Optional_PK_Inverse3Id], [t4].[PeriodEnd], [t4].[PeriodStart], [t4].[Id0], [t4].[Level3_Optional_Id], [t4].[Level3_Required_Id], [t4].[Level4_Name], [t4].[OneToMany_Optional_Inverse4Id], [t4].[OneToMany_Required_Inverse4Id], [t4].[OneToOne_Optional_PK_Inverse4Id], [t4].[PeriodEnd0], [t4].[PeriodStart0], [t4].[Id1], [t4].[Id00], [t4].[Id01], [t4].[Id000], [t4].[Id0000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Required_Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[OneToOne_Optional_PK_Inverse2Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[OneToOne_Required_PK_Date], [l2].[Level1_Optional_Id], [l2].[Level1_Required_Id], [l2].[Level2_Name], [l2].[OneToMany_Optional_Inverse2Id], [l2].[OneToMany_Required_Inverse2Id], [l2].[OneToOne_Optional_PK_Inverse2Id], [l2].[PeriodEnd], [l2].[PeriodStart], [l3].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] ON [l2].[Id] = [l3].[Id] + WHERE [l2].[OneToOne_Required_PK_Date] IS NOT NULL AND [l2].[Level1_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t0] ON [l].[Id] = [t0].[Level1_Optional_Id] +LEFT JOIN ( + SELECT [t2].[Id], [t2].[Level2_Optional_Id], [t2].[Level2_Required_Id], [t2].[Level3_Name], [t2].[OneToMany_Optional_Inverse3Id], [t2].[OneToMany_Required_Inverse3Id], [t2].[OneToOne_Optional_PK_Inverse3Id], [t2].[PeriodEnd], [t2].[PeriodStart], [t2].[Id0], [t2].[Id00], [t2].[c] + FROM ( + SELECT [l4].[Id], [l4].[Level2_Optional_Id], [l4].[Level2_Required_Id], [l4].[Level3_Name], [l4].[OneToMany_Optional_Inverse3Id], [l4].[OneToMany_Required_Inverse3Id], [l4].[OneToOne_Optional_PK_Inverse3Id], [l4].[PeriodEnd], [l4].[PeriodStart], [t3].[Id] AS [Id0], [t3].[Id0] AS [Id00], ROW_NUMBER() OVER(PARTITION BY [l4].[OneToMany_Optional_Inverse3Id] ORDER BY CASE + WHEN [l4].[Level2_Required_Id] IS NOT NULL AND [l4].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [l4].[Id] + END) AS [row], CASE + WHEN [l4].[Level2_Required_Id] IS NOT NULL AND [l4].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [l4].[Id] + END AS [c] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] + INNER JOIN ( + SELECT [l5].[Id], [l6].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] ON [l5].[Id] = [l6].[Id] + WHERE [l5].[OneToOne_Required_PK_Date] IS NOT NULL AND [l5].[Level1_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t3] ON [l4].[Id] = [t3].[Id] + WHERE [l4].[Level2_Required_Id] IS NOT NULL AND [l4].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t2] + WHERE [t2].[row] <= 3 +) AS [t1] ON CASE + WHEN [t0].[OneToOne_Required_PK_Date] IS NOT NULL AND [t0].[Level1_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t0].[PeriodEnd] IS NOT NULL AND [t0].[PeriodStart] IS NOT NULL THEN [t0].[Id] +END = [t1].[OneToMany_Optional_Inverse3Id] +LEFT JOIN ( + SELECT [l7].[Id], [l7].[Level2_Optional_Id], [l7].[Level2_Required_Id], [l7].[Level3_Name], [l7].[OneToMany_Optional_Inverse3Id], [l7].[OneToMany_Required_Inverse3Id], [l7].[OneToOne_Optional_PK_Inverse3Id], [l7].[PeriodEnd], [l7].[PeriodStart], [t6].[Id] AS [Id0], [t6].[Level3_Optional_Id], [t6].[Level3_Required_Id], [t6].[Level4_Name], [t6].[OneToMany_Optional_Inverse4Id], [t6].[OneToMany_Required_Inverse4Id], [t6].[OneToOne_Optional_PK_Inverse4Id], [t6].[PeriodEnd] AS [PeriodEnd0], [t6].[PeriodStart] AS [PeriodStart0], [t5].[Id] AS [Id1], [t5].[Id0] AS [Id00], [t6].[Id0] AS [Id01], [t6].[Id00] AS [Id000], [t6].[Id000] AS [Id0000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] + INNER JOIN ( + SELECT [l8].[Id], [l9].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l9] ON [l8].[Id] = [l9].[Id] + WHERE [l8].[OneToOne_Required_PK_Date] IS NOT NULL AND [l8].[Level1_Required_Id] IS NOT NULL AND [l8].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t5] ON [l7].[Id] = [t5].[Id] + LEFT JOIN ( + SELECT [l10].[Id], [l10].[Level3_Optional_Id], [l10].[Level3_Required_Id], [l10].[Level4_Name], [l10].[OneToMany_Optional_Inverse4Id], [l10].[OneToMany_Required_Inverse4Id], [l10].[OneToOne_Optional_PK_Inverse4Id], [l10].[PeriodEnd], [l10].[PeriodStart], [t7].[Id] AS [Id0], [t7].[Id0] AS [Id00], [t7].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l10] + INNER JOIN ( + SELECT [l11].[Id], [t8].[Id] AS [Id0], [t8].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l11] + INNER JOIN ( + SELECT [l12].[Id], [l13].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l12] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l13] ON [l12].[Id] = [l13].[Id] + WHERE [l12].[OneToOne_Required_PK_Date] IS NOT NULL AND [l12].[Level1_Required_Id] IS NOT NULL AND [l12].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t8] ON [l11].[Id] = [t8].[Id] + WHERE [l11].[Level2_Required_Id] IS NOT NULL AND [l11].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t7] ON [l10].[Id] = [t7].[Id] + WHERE [l10].[Level3_Required_Id] IS NOT NULL AND [l10].[OneToMany_Required_Inverse4Id] IS NOT NULL + ) AS [t6] ON CASE + WHEN [l7].[Level2_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [l7].[Id] + END = [t6].[Level3_Optional_Id] + WHERE [l7].[Level2_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t4] ON CASE + WHEN [t0].[OneToOne_Required_PK_Date] IS NOT NULL AND [t0].[Level1_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t0].[PeriodEnd] IS NOT NULL AND [t0].[PeriodStart] IS NOT NULL THEN [t0].[Id] +END = [t4].[OneToMany_Required_Inverse3Id] +WHERE CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END < 3 OR CASE + WHEN [t0].[OneToOne_Required_PK_Date] IS NOT NULL AND [t0].[Level1_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t0].[PeriodEnd] IS NOT NULL AND [t0].[PeriodStart] IS NOT NULL THEN [t0].[Id] +END > 8 +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0], [t1].[OneToMany_Optional_Inverse3Id], [t1].[c], [t1].[Id], [t1].[Id0], [t1].[Id00], [t4].[Id], [t4].[Id1], [t4].[Id00], [t4].[Id0], [t4].[Id01], [t4].[Id000]"); + } + + public override async Task Include_reference_and_collection_order_by(bool async) + { + await base.Include_reference_and_collection_order_by(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0], [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t0].[Id00] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[Level1_Optional_Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END = [t0].[OneToMany_Optional_Inverse3Id] +ORDER BY [l].[Name], [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0]"); + } + + public override async Task Include_reference_collection_order_by_reference_navigation(bool async) + { + await base.Include_reference_collection_order_by_reference_navigation(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0], [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t0].[Id00] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[Level1_Optional_Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END = [t0].[OneToMany_Optional_Inverse3Id] +ORDER BY CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END, [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0]"); + } + + public override async Task Include_reference_followed_by_include_collection(bool async) + { + await base.Include_reference_followed_by_include_collection(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0], [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t0].[Id00] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[Level1_Optional_Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END = [t0].[OneToMany_Optional_Inverse3Id] +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0]"); + } + + public override async Task Include_reference_ThenInclude_collection_order_by(bool async) + { + await base.Include_reference_ThenInclude_collection_order_by(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0], [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t0].[Id00] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[Level1_Optional_Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END = [t0].[OneToMany_Optional_Inverse3Id] +ORDER BY [l].[Name], [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0]"); + } + + public override async Task Include_ThenInclude_ThenInclude_followed_by_two_nested_selects(bool async) + { + await base.Include_ThenInclude_ThenInclude_followed_by_two_nested_selects(async); + + AssertSql( + @"SELECT [l].[Id], [t4].[Id], [t4].[Level2_Optional_Id], [t4].[Level2_Required_Id], [t4].[Level3_Name], [t4].[OneToMany_Optional_Inverse3Id], [t4].[OneToMany_Required_Inverse3Id], [t4].[OneToOne_Optional_PK_Inverse3Id], [t4].[PeriodEnd], [t4].[PeriodStart], [t4].[Id0], [t4].[Level3_Optional_Id], [t4].[Level3_Required_Id], [t4].[Level4_Name], [t4].[OneToMany_Optional_Inverse4Id], [t4].[OneToMany_Required_Inverse4Id], [t4].[OneToOne_Optional_PK_Inverse4Id], [t4].[PeriodEnd0], [t4].[PeriodStart0], [t4].[Id1], [t4].[Id2], [t4].[Id00], [t4].[Id000], [t4].[Id01], [t4].[Id001], [t4].[Id0000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Level3_Optional_Id], [t1].[Level3_Required_Id], [t1].[Level4_Name], [t1].[OneToMany_Optional_Inverse4Id], [t1].[OneToMany_Required_Inverse4Id], [t1].[OneToOne_Optional_PK_Inverse4Id], [t1].[PeriodEnd] AS [PeriodEnd0], [t1].[PeriodStart] AS [PeriodStart0], [l0].[Id] AS [Id1], [l1].[Id] AS [Id2], [t0].[Id0] AS [Id00], [t0].[Id00] AS [Id000], [t1].[Id0] AS [Id01], [t1].[Id00] AS [Id001], [t1].[Id000] AS [Id0000], [l0].[OneToMany_Optional_Inverse2Id] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t].[Id] AS [Id0], [t].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] ON [l2].[Id] = [t].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t0] ON CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END = [t0].[OneToOne_Optional_PK_Inverse3Id] + LEFT JOIN ( + SELECT [l5].[Id], [l5].[Level3_Optional_Id], [l5].[Level3_Required_Id], [l5].[Level4_Name], [l5].[OneToMany_Optional_Inverse4Id], [l5].[OneToMany_Required_Inverse4Id], [l5].[OneToOne_Optional_PK_Inverse4Id], [l5].[PeriodEnd], [l5].[PeriodStart], [t2].[Id] AS [Id0], [t2].[Id0] AS [Id00], [t2].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN ( + SELECT [l6].[Id], [t3].[Id] AS [Id0], [t3].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] + INNER JOIN ( + SELECT [l7].[Id], [l8].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] ON [l7].[Id] = [l8].[Id] + WHERE [l7].[OneToOne_Required_PK_Date] IS NOT NULL AND [l7].[Level1_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t3] ON [l6].[Id] = [t3].[Id] + WHERE [l6].[Level2_Required_Id] IS NOT NULL AND [l6].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t2] ON [l5].[Id] = [t2].[Id] + WHERE [l5].[Level3_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse4Id] IS NOT NULL + ) AS [t1] ON CASE + WHEN [t0].[Level2_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse3Id] IS NOT NULL AND [t0].[PeriodEnd] IS NOT NULL AND [t0].[PeriodStart] IS NOT NULL THEN [t0].[Id] + END = [t1].[Level3_Optional_Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t4] ON [l].[Id] = [t4].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t4].[Id1], [t4].[Id2], [t4].[Id], [t4].[Id00], [t4].[Id000], [t4].[Id0], [t4].[Id01], [t4].[Id001]"); + } + + public override async Task Including_reference_navigation_and_projecting_collection_navigation(bool async) + { + await base.Including_reference_navigation_and_projecting_collection_navigation(async); + + AssertSql( + @"SELECT [l].[Id], [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t].[Id0], [t0].[Id0], [t0].[Id00], [t2].[Id], [t2].[OneToOne_Required_PK_Date], [t2].[Level1_Optional_Id], [t2].[Level1_Required_Id], [t2].[Level2_Name], [t2].[OneToMany_Optional_Inverse2Id], [t2].[OneToMany_Required_Inverse2Id], [t2].[OneToOne_Optional_PK_Inverse2Id], [t2].[PeriodEnd], [t2].[PeriodStart], [t2].[Id0] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[Level1_Required_Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END = [t0].[Level2_Optional_Id] +LEFT JOIN ( + SELECT [l5].[Id], [l5].[OneToOne_Required_PK_Date], [l5].[Level1_Optional_Id], [l5].[Level1_Required_Id], [l5].[Level2_Name], [l5].[OneToMany_Optional_Inverse2Id], [l5].[OneToMany_Required_Inverse2Id], [l5].[OneToOne_Optional_PK_Inverse2Id], [l5].[PeriodEnd], [l5].[PeriodStart], [l6].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] ON [l5].[Id] = [l6].[Id] + WHERE [l5].[OneToOne_Required_PK_Date] IS NOT NULL AND [l5].[Level1_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t2] ON [l].[Id] = [t2].[OneToMany_Required_Inverse2Id] +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0], [t0].[Id00], [t2].[Id]"); + } + + public override async Task LeftJoin_with_Any_on_outer_source_and_projecting_collection_from_inner(bool async) + { + await base.LeftJoin_with_Any_on_outer_source_and_projecting_collection_from_inner(async); + + AssertSql( + @"SELECT CASE + WHEN [t0].[OneToOne_Required_PK_Date] IS NULL OR [t0].[Level1_Required_Id] IS NULL OR [t0].[OneToMany_Required_Inverse2Id] IS NULL OR CASE + WHEN [t0].[PeriodEnd0] IS NOT NULL AND [t0].[PeriodStart0] IS NOT NULL THEN [t0].[PeriodEnd0] + END IS NULL OR CASE + WHEN [t0].[PeriodEnd0] IS NOT NULL AND [t0].[PeriodStart0] IS NOT NULL THEN [t0].[PeriodStart0] + END IS NULL THEN 0 + WHEN [t0].[OneToOne_Required_PK_Date] IS NOT NULL AND [t0].[Level1_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t0].[PeriodEnd0] IS NOT NULL AND [t0].[PeriodStart0] IS NOT NULL THEN [t0].[Id0] +END, [l].[Id], [t0].[Id], [t0].[Id0], [t0].[Id00], [t1].[Id], [t1].[Level2_Optional_Id], [t1].[Level2_Required_Id], [t1].[Level3_Name], [t1].[OneToMany_Optional_Inverse3Id], [t1].[OneToMany_Required_Inverse3Id], [t1].[OneToOne_Optional_PK_Inverse3Id], [t1].[PeriodEnd], [t1].[PeriodStart], [t1].[Id0], [t1].[Id00] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [t].[Id] AS [Id0], [t].[OneToOne_Required_PK_Date], [t].[Level1_Required_Id], [t].[OneToMany_Required_Inverse2Id], [t].[PeriodEnd] AS [PeriodEnd0], [t].[PeriodStart] AS [PeriodStart0], [t].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + LEFT JOIN ( + SELECT [l1].[Id], [l1].[OneToOne_Required_PK_Date], [l1].[Level1_Required_Id], [l1].[OneToMany_Required_Inverse2Id], [l1].[PeriodEnd], [l1].[PeriodStart], [l2].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] ON [l1].[Id] = [l2].[Id] + WHERE [l1].[OneToOne_Required_PK_Date] IS NOT NULL AND [l1].[Level1_Required_Id] IS NOT NULL AND [l1].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] ON [l0].[Id] = CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] + END + WHERE [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[PeriodEnd] + END IS NOT NULL AND CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[PeriodStart] + END IS NOT NULL +) AS [t0] ON [l].[Id] = [t0].[Level1_Required_Id] +LEFT JOIN ( + SELECT [l3].[Id], [l3].[Level2_Optional_Id], [l3].[Level2_Required_Id], [l3].[Level3_Name], [l3].[OneToMany_Optional_Inverse3Id], [l3].[OneToMany_Required_Inverse3Id], [l3].[OneToOne_Optional_PK_Inverse3Id], [l3].[PeriodEnd], [l3].[PeriodStart], [t2].[Id] AS [Id0], [t2].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN ( + SELECT [l4].[Id], [l5].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] ON [l4].[Id] = [l5].[Id] + WHERE [l4].[OneToOne_Required_PK_Date] IS NOT NULL AND [l4].[Level1_Required_Id] IS NOT NULL AND [l4].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t2] ON [l3].[Id] = [t2].[Id] + WHERE [l3].[Level2_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t1] ON CASE + WHEN [t0].[OneToOne_Required_PK_Date] IS NOT NULL AND [t0].[Level1_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t0].[PeriodEnd0] IS NOT NULL AND [t0].[PeriodStart0] IS NOT NULL THEN [t0].[Id0] +END = [t1].[OneToMany_Required_Inverse3Id] +WHERE [l].[Name] IN (N'L1 01', N'L1 02') +ORDER BY [l].[Id], [t0].[Id], [t0].[Id0], [t0].[Id00], [t1].[Id], [t1].[Id0]"); + } + + public override async Task Lift_projection_mapping_when_pushing_down_subquery(bool async) + { + await base.Lift_projection_mapping_when_pushing_down_subquery(async); + + AssertSql( + @"@__p_0='25' + +SELECT [t].[Id], [t0].[Id0], [t0].[Id1], [t2].[Id], [t2].[Id0], [t2].[Id1], [t0].[Id], [t0].[c] +FROM ( + SELECT TOP(@__p_0) [l].[Id] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +) AS [t] +LEFT JOIN ( + SELECT [t1].[Id], [t1].[c], [t1].[Id0], [t1].[Id1], [t1].[OneToMany_Required_Inverse2Id] + FROM ( + SELECT CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END AS [Id], 1 AS [c], [l0].[Id] AS [Id0], [l1].[Id] AS [Id1], [l0].[OneToMany_Required_Inverse2Id], ROW_NUMBER() OVER(PARTITION BY [l0].[OneToMany_Required_Inverse2Id] ORDER BY [l0].[Id], [l1].[Id]) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] + WHERE [t1].[row] <= 1 +) AS [t0] ON [t].[Id] = [t0].[OneToMany_Required_Inverse2Id] +LEFT JOIN ( + SELECT CASE + WHEN [l2].[OneToOne_Required_PK_Date] IS NOT NULL AND [l2].[Level1_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l2].[Id] + END AS [Id], [l2].[Id] AS [Id0], [l3].[Id] AS [Id1], [l2].[OneToMany_Required_Inverse2Id] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] ON [l2].[Id] = [l3].[Id] + WHERE [l2].[OneToOne_Required_PK_Date] IS NOT NULL AND [l2].[Level1_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t2] ON [t].[Id] = [t2].[OneToMany_Required_Inverse2Id] +ORDER BY [t].[Id], [t0].[Id0], [t0].[Id1], [t2].[Id0]"); + } + + public override async Task Multiple_complex_includes(bool async) + { + await base.Multiple_complex_includes(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0], [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t0].[Id00], [t2].[Id], [t2].[OneToOne_Required_PK_Date], [t2].[Level1_Optional_Id], [t2].[Level1_Required_Id], [t2].[Level2_Name], [t2].[OneToMany_Optional_Inverse2Id], [t2].[OneToMany_Required_Inverse2Id], [t2].[OneToOne_Optional_PK_Inverse2Id], [t2].[PeriodEnd], [t2].[PeriodStart], [t2].[Id0], [t2].[Level2_Optional_Id], [t2].[Level2_Required_Id], [t2].[Level3_Name], [t2].[OneToMany_Optional_Inverse3Id], [t2].[OneToMany_Required_Inverse3Id], [t2].[OneToOne_Optional_PK_Inverse3Id], [t2].[PeriodEnd0], [t2].[PeriodStart0], [t2].[Id1], [t2].[Id00], [t2].[Id000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[Level1_Optional_Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END = [t0].[OneToMany_Optional_Inverse3Id] +LEFT JOIN ( + SELECT [l5].[Id], [l5].[OneToOne_Required_PK_Date], [l5].[Level1_Optional_Id], [l5].[Level1_Required_Id], [l5].[Level2_Name], [l5].[OneToMany_Optional_Inverse2Id], [l5].[OneToMany_Required_Inverse2Id], [l5].[OneToOne_Optional_PK_Inverse2Id], [l5].[PeriodEnd], [l5].[PeriodStart], [t3].[Id] AS [Id0], [t3].[Level2_Optional_Id], [t3].[Level2_Required_Id], [t3].[Level3_Name], [t3].[OneToMany_Optional_Inverse3Id], [t3].[OneToMany_Required_Inverse3Id], [t3].[OneToOne_Optional_PK_Inverse3Id], [t3].[PeriodEnd] AS [PeriodEnd0], [t3].[PeriodStart] AS [PeriodStart0], [l6].[Id] AS [Id1], [t3].[Id0] AS [Id00], [t3].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] ON [l5].[Id] = [l6].[Id] + LEFT JOIN ( + SELECT [l7].[Id], [l7].[Level2_Optional_Id], [l7].[Level2_Required_Id], [l7].[Level3_Name], [l7].[OneToMany_Optional_Inverse3Id], [l7].[OneToMany_Required_Inverse3Id], [l7].[OneToOne_Optional_PK_Inverse3Id], [l7].[PeriodEnd], [l7].[PeriodStart], [t4].[Id] AS [Id0], [t4].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] + INNER JOIN ( + SELECT [l8].[Id], [l9].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l9] ON [l8].[Id] = [l9].[Id] + WHERE [l8].[OneToOne_Required_PK_Date] IS NOT NULL AND [l8].[Level1_Required_Id] IS NOT NULL AND [l8].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t4] ON [l7].[Id] = [t4].[Id] + WHERE [l7].[Level2_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t3] ON CASE + WHEN [l5].[OneToOne_Required_PK_Date] IS NOT NULL AND [l5].[Level1_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l5].[Id] + END = [t3].[Level2_Optional_Id] + WHERE [l5].[OneToOne_Required_PK_Date] IS NOT NULL AND [l5].[Level1_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t2] ON [l].[Id] = [t2].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0], [t0].[Id00], [t2].[Id], [t2].[Id1], [t2].[Id0], [t2].[Id00]"); + } + + public override async Task Multiple_complex_include_select(bool async) + { + await base.Multiple_complex_include_select(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0], [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t0].[Id00], [t2].[Id], [t2].[OneToOne_Required_PK_Date], [t2].[Level1_Optional_Id], [t2].[Level1_Required_Id], [t2].[Level2_Name], [t2].[OneToMany_Optional_Inverse2Id], [t2].[OneToMany_Required_Inverse2Id], [t2].[OneToOne_Optional_PK_Inverse2Id], [t2].[PeriodEnd], [t2].[PeriodStart], [t2].[Id0], [t2].[Level2_Optional_Id], [t2].[Level2_Required_Id], [t2].[Level3_Name], [t2].[OneToMany_Optional_Inverse3Id], [t2].[OneToMany_Required_Inverse3Id], [t2].[OneToOne_Optional_PK_Inverse3Id], [t2].[PeriodEnd0], [t2].[PeriodStart0], [t2].[Id1], [t2].[Id00], [t2].[Id000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[Level1_Optional_Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END = [t0].[OneToMany_Optional_Inverse3Id] +LEFT JOIN ( + SELECT [l5].[Id], [l5].[OneToOne_Required_PK_Date], [l5].[Level1_Optional_Id], [l5].[Level1_Required_Id], [l5].[Level2_Name], [l5].[OneToMany_Optional_Inverse2Id], [l5].[OneToMany_Required_Inverse2Id], [l5].[OneToOne_Optional_PK_Inverse2Id], [l5].[PeriodEnd], [l5].[PeriodStart], [t3].[Id] AS [Id0], [t3].[Level2_Optional_Id], [t3].[Level2_Required_Id], [t3].[Level3_Name], [t3].[OneToMany_Optional_Inverse3Id], [t3].[OneToMany_Required_Inverse3Id], [t3].[OneToOne_Optional_PK_Inverse3Id], [t3].[PeriodEnd] AS [PeriodEnd0], [t3].[PeriodStart] AS [PeriodStart0], [l6].[Id] AS [Id1], [t3].[Id0] AS [Id00], [t3].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] ON [l5].[Id] = [l6].[Id] + LEFT JOIN ( + SELECT [l7].[Id], [l7].[Level2_Optional_Id], [l7].[Level2_Required_Id], [l7].[Level3_Name], [l7].[OneToMany_Optional_Inverse3Id], [l7].[OneToMany_Required_Inverse3Id], [l7].[OneToOne_Optional_PK_Inverse3Id], [l7].[PeriodEnd], [l7].[PeriodStart], [t4].[Id] AS [Id0], [t4].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] + INNER JOIN ( + SELECT [l8].[Id], [l9].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l9] ON [l8].[Id] = [l9].[Id] + WHERE [l8].[OneToOne_Required_PK_Date] IS NOT NULL AND [l8].[Level1_Required_Id] IS NOT NULL AND [l8].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t4] ON [l7].[Id] = [t4].[Id] + WHERE [l7].[Level2_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t3] ON CASE + WHEN [l5].[OneToOne_Required_PK_Date] IS NOT NULL AND [l5].[Level1_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l5].[Id] + END = [t3].[Level2_Optional_Id] + WHERE [l5].[OneToOne_Required_PK_Date] IS NOT NULL AND [l5].[Level1_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t2] ON [l].[Id] = [t2].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0], [t0].[Id00], [t2].[Id], [t2].[Id1], [t2].[Id0], [t2].[Id00]"); + } + + public override async Task Multiple_include_with_multiple_optional_navigations(bool async) + { + await base.Multiple_include_with_multiple_optional_navigations(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0], [t0].[Id], [t0].[Id0], [t0].[Id00], [t2].[Id], [t2].[Id0], [t2].[Id00], [t4].[Id], [t4].[Id0], [t5].[Id], [t5].[Id0], [t5].[Id00], [t7].[Id], [t7].[Level2_Optional_Id], [t7].[Level2_Required_Id], [t7].[Level3_Name], [t7].[OneToMany_Optional_Inverse3Id], [t7].[OneToMany_Required_Inverse3Id], [t7].[OneToOne_Optional_PK_Inverse3Id], [t7].[PeriodEnd], [t7].[PeriodStart], [t7].[Id0], [t7].[Id00], [t2].[Level2_Optional_Id], [t2].[Level2_Required_Id], [t2].[Level3_Name], [t2].[OneToMany_Optional_Inverse3Id], [t2].[OneToMany_Required_Inverse3Id], [t2].[OneToOne_Optional_PK_Inverse3Id], [t2].[PeriodEnd], [t2].[PeriodStart], [t4].[OneToOne_Required_PK_Date], [t4].[Level1_Optional_Id], [t4].[Level1_Required_Id], [t4].[Level2_Name], [t4].[OneToMany_Optional_Inverse2Id], [t4].[OneToMany_Required_Inverse2Id], [t4].[OneToOne_Optional_PK_Inverse2Id], [t4].[PeriodEnd], [t4].[PeriodStart], [t5].[Level2_Optional_Id], [t5].[Level2_Required_Id], [t5].[Level3_Name], [t5].[OneToMany_Optional_Inverse3Id], [t5].[OneToMany_Required_Inverse3Id], [t5].[OneToOne_Optional_PK_Inverse3Id], [t5].[PeriodEnd], [t5].[PeriodStart] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[Level1_Required_Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level3_Name], [l2].[OneToOne_Optional_PK_Inverse3Id], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END = [t0].[OneToOne_Optional_PK_Inverse3Id] +LEFT JOIN ( + SELECT [l5].[Id], [l5].[Level2_Optional_Id], [l5].[Level2_Required_Id], [l5].[Level3_Name], [l5].[OneToMany_Optional_Inverse3Id], [l5].[OneToMany_Required_Inverse3Id], [l5].[OneToOne_Optional_PK_Inverse3Id], [l5].[PeriodEnd], [l5].[PeriodStart], [t3].[Id] AS [Id0], [t3].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN ( + SELECT [l6].[Id], [l7].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] ON [l6].[Id] = [l7].[Id] + WHERE [l6].[OneToOne_Required_PK_Date] IS NOT NULL AND [l6].[Level1_Required_Id] IS NOT NULL AND [l6].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t3] ON [l5].[Id] = [t3].[Id] + WHERE [l5].[Level2_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t2] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END = [t2].[Level2_Optional_Id] +LEFT JOIN ( + SELECT [l8].[Id], [l8].[OneToOne_Required_PK_Date], [l8].[Level1_Optional_Id], [l8].[Level1_Required_Id], [l8].[Level2_Name], [l8].[OneToMany_Optional_Inverse2Id], [l8].[OneToMany_Required_Inverse2Id], [l8].[OneToOne_Optional_PK_Inverse2Id], [l8].[PeriodEnd], [l8].[PeriodStart], [l9].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l9] ON [l8].[Id] = [l9].[Id] + WHERE [l8].[OneToOne_Required_PK_Date] IS NOT NULL AND [l8].[Level1_Required_Id] IS NOT NULL AND [l8].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t4] ON [l].[Id] = [t4].[Level1_Optional_Id] +LEFT JOIN ( + SELECT [l10].[Id], [l10].[Level2_Optional_Id], [l10].[Level2_Required_Id], [l10].[Level3_Name], [l10].[OneToMany_Optional_Inverse3Id], [l10].[OneToMany_Required_Inverse3Id], [l10].[OneToOne_Optional_PK_Inverse3Id], [l10].[PeriodEnd], [l10].[PeriodStart], [t6].[Id] AS [Id0], [t6].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l10] + INNER JOIN ( + SELECT [l11].[Id], [l12].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l11] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l12] ON [l11].[Id] = [l12].[Id] + WHERE [l11].[OneToOne_Required_PK_Date] IS NOT NULL AND [l11].[Level1_Required_Id] IS NOT NULL AND [l11].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t6] ON [l10].[Id] = [t6].[Id] + WHERE [l10].[Level2_Required_Id] IS NOT NULL AND [l10].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t5] ON CASE + WHEN [t4].[OneToOne_Required_PK_Date] IS NOT NULL AND [t4].[Level1_Required_Id] IS NOT NULL AND [t4].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t4].[PeriodEnd] IS NOT NULL AND [t4].[PeriodStart] IS NOT NULL THEN [t4].[Id] +END = [t5].[Level2_Optional_Id] +LEFT JOIN ( + SELECT [l13].[Id], [l13].[Level2_Optional_Id], [l13].[Level2_Required_Id], [l13].[Level3_Name], [l13].[OneToMany_Optional_Inverse3Id], [l13].[OneToMany_Required_Inverse3Id], [l13].[OneToOne_Optional_PK_Inverse3Id], [l13].[PeriodEnd], [l13].[PeriodStart], [t8].[Id] AS [Id0], [t8].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l13] + INNER JOIN ( + SELECT [l14].[Id], [l15].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l14] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l15] ON [l14].[Id] = [l15].[Id] + WHERE [l14].[OneToOne_Required_PK_Date] IS NOT NULL AND [l14].[Level1_Required_Id] IS NOT NULL AND [l14].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t8] ON [l13].[Id] = [t8].[Id] + WHERE [l13].[Level2_Required_Id] IS NOT NULL AND [l13].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t7] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END = [t7].[OneToMany_Optional_Inverse3Id] +WHERE [t0].[Level3_Name] <> N'Foo' OR [t0].[Level3_Name] IS NULL +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0], [t0].[Id00], [t2].[Id], [t2].[Id0], [t2].[Id00], [t4].[Id], [t4].[Id0], [t5].[Id], [t5].[Id0], [t5].[Id00], [t7].[Id], [t7].[Id0]"); + } + + public override async Task Multiple_optional_navigation_with_Include(bool async) + { + await base.Multiple_optional_navigation_with_Include(async); + + AssertSql( + @"SELECT [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [l].[Id], [t].[Id], [t].[Id0], [t0].[Id0], [t0].[Id00], [t2].[Id], [t2].[Level3_Optional_Id], [t2].[Level3_Required_Id], [t2].[Level4_Name], [t2].[OneToMany_Optional_Inverse4Id], [t2].[OneToMany_Required_Inverse4Id], [t2].[OneToOne_Optional_PK_Inverse4Id], [t2].[PeriodEnd], [t2].[PeriodStart], [t2].[Id0], [t2].[Id00], [t2].[Id000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[Level1_Optional_Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END = [t0].[OneToOne_Optional_PK_Inverse3Id] +LEFT JOIN ( + SELECT [l5].[Id], [l5].[Level3_Optional_Id], [l5].[Level3_Required_Id], [l5].[Level4_Name], [l5].[OneToMany_Optional_Inverse4Id], [l5].[OneToMany_Required_Inverse4Id], [l5].[OneToOne_Optional_PK_Inverse4Id], [l5].[PeriodEnd], [l5].[PeriodStart], [t3].[Id] AS [Id0], [t3].[Id0] AS [Id00], [t3].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN ( + SELECT [l6].[Id], [t4].[Id] AS [Id0], [t4].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] + INNER JOIN ( + SELECT [l7].[Id], [l8].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] ON [l7].[Id] = [l8].[Id] + WHERE [l7].[OneToOne_Required_PK_Date] IS NOT NULL AND [l7].[Level1_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t4] ON [l6].[Id] = [t4].[Id] + WHERE [l6].[Level2_Required_Id] IS NOT NULL AND [l6].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t3] ON [l5].[Id] = [t3].[Id] + WHERE [l5].[Level3_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse4Id] IS NOT NULL +) AS [t2] ON CASE + WHEN [t0].[Level2_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse3Id] IS NOT NULL AND [t0].[PeriodEnd] IS NOT NULL AND [t0].[PeriodStart] IS NOT NULL THEN [t0].[Id] +END = [t2].[OneToMany_Optional_Inverse4Id] +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0], [t0].[Id00], [t2].[Id], [t2].[Id0], [t2].[Id00]"); + } + + public override async Task Multiple_optional_navigation_with_string_based_Include(bool async) + { + await base.Multiple_optional_navigation_with_string_based_Include(async); + + AssertSql( + @"SELECT [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [l].[Id], [t].[Id], [t].[Id0], [t0].[Id0], [t0].[Id00], [t2].[Id], [t2].[Level3_Optional_Id], [t2].[Level3_Required_Id], [t2].[Level4_Name], [t2].[OneToMany_Optional_Inverse4Id], [t2].[OneToMany_Required_Inverse4Id], [t2].[OneToOne_Optional_PK_Inverse4Id], [t2].[PeriodEnd], [t2].[PeriodStart], [t2].[Id0], [t2].[Id00], [t2].[Id000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[Level1_Optional_Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END = [t0].[OneToOne_Optional_PK_Inverse3Id] +LEFT JOIN ( + SELECT [l5].[Id], [l5].[Level3_Optional_Id], [l5].[Level3_Required_Id], [l5].[Level4_Name], [l5].[OneToMany_Optional_Inverse4Id], [l5].[OneToMany_Required_Inverse4Id], [l5].[OneToOne_Optional_PK_Inverse4Id], [l5].[PeriodEnd], [l5].[PeriodStart], [t3].[Id] AS [Id0], [t3].[Id0] AS [Id00], [t3].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN ( + SELECT [l6].[Id], [t4].[Id] AS [Id0], [t4].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] + INNER JOIN ( + SELECT [l7].[Id], [l8].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] ON [l7].[Id] = [l8].[Id] + WHERE [l7].[OneToOne_Required_PK_Date] IS NOT NULL AND [l7].[Level1_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t4] ON [l6].[Id] = [t4].[Id] + WHERE [l6].[Level2_Required_Id] IS NOT NULL AND [l6].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t3] ON [l5].[Id] = [t3].[Id] + WHERE [l5].[Level3_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse4Id] IS NOT NULL +) AS [t2] ON CASE + WHEN [t0].[Level2_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse3Id] IS NOT NULL AND [t0].[PeriodEnd] IS NOT NULL AND [t0].[PeriodStart] IS NOT NULL THEN [t0].[Id] +END = [t2].[OneToMany_Optional_Inverse4Id] +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0], [t0].[Id00], [t2].[Id], [t2].[Id0], [t2].[Id00]"); + } + + public override async Task Multiple_SelectMany_navigation_property_followed_by_select_collection_navigation(bool async) + { + await base.Multiple_SelectMany_navigation_property_followed_by_select_collection_navigation(async); + + AssertSql( + @"SELECT CASE + WHEN [t0].[Level2_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [t0].[Id] +END, [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0], [t0].[Id00], [t2].[Id], [t2].[Level3_Optional_Id], [t2].[Level3_Required_Id], [t2].[Level4_Name], [t2].[OneToMany_Optional_Inverse4Id], [t2].[OneToMany_Required_Inverse4Id], [t2].[OneToOne_Optional_PK_Inverse4Id], [t2].[PeriodEnd], [t2].[PeriodStart], [t2].[Id0], [t2].[Id00], [t2].[Id000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +INNER JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Required_Id], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[OneToMany_Optional_Inverse2Id] +INNER JOIN ( + SELECT [l2].[Id], [l2].[Level2_Required_Id], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] +END = [t0].[OneToMany_Optional_Inverse3Id] +LEFT JOIN ( + SELECT [l5].[Id], [l5].[Level3_Optional_Id], [l5].[Level3_Required_Id], [l5].[Level4_Name], [l5].[OneToMany_Optional_Inverse4Id], [l5].[OneToMany_Required_Inverse4Id], [l5].[OneToOne_Optional_PK_Inverse4Id], [l5].[PeriodEnd], [l5].[PeriodStart], [t3].[Id] AS [Id0], [t3].[Id0] AS [Id00], [t3].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN ( + SELECT [l6].[Id], [t4].[Id] AS [Id0], [t4].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] + INNER JOIN ( + SELECT [l7].[Id], [l8].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] ON [l7].[Id] = [l8].[Id] + WHERE [l7].[OneToOne_Required_PK_Date] IS NOT NULL AND [l7].[Level1_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t4] ON [l6].[Id] = [t4].[Id] + WHERE [l6].[Level2_Required_Id] IS NOT NULL AND [l6].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t3] ON [l5].[Id] = [t3].[Id] + WHERE [l5].[Level3_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse4Id] IS NOT NULL +) AS [t2] ON CASE + WHEN [t0].[Level2_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [t0].[Id] +END = [t2].[OneToMany_Optional_Inverse4Id] +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0], [t0].[Id00], [t2].[Id], [t2].[Id0], [t2].[Id00]"); + } + + public override async Task Multiple_SelectMany_with_Include(bool async) + { + await base.Multiple_SelectMany_with_Include(async); + + AssertSql( + @"SELECT [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t2].[Id], [t2].[Level3_Optional_Id], [t2].[Level3_Required_Id], [t2].[Level4_Name], [t2].[OneToMany_Optional_Inverse4Id], [t2].[OneToMany_Required_Inverse4Id], [t2].[OneToOne_Optional_PK_Inverse4Id], [t2].[PeriodEnd], [t2].[PeriodStart], [l].[Id], [t].[Id], [t].[Id0], [t0].[Id0], [t0].[Id00], [t2].[Id0], [t2].[Id00], [t2].[Id000], [t5].[Id], [t5].[Level3_Optional_Id], [t5].[Level3_Required_Id], [t5].[Level4_Name], [t5].[OneToMany_Optional_Inverse4Id], [t5].[OneToMany_Required_Inverse4Id], [t5].[OneToOne_Optional_PK_Inverse4Id], [t5].[PeriodEnd], [t5].[PeriodStart], [t5].[Id0], [t5].[Id00], [t5].[Id000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +INNER JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Required_Id], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[OneToMany_Optional_Inverse2Id] +INNER JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] +END = [t0].[OneToMany_Optional_Inverse3Id] +LEFT JOIN ( + SELECT [l5].[Id], [l5].[Level3_Optional_Id], [l5].[Level3_Required_Id], [l5].[Level4_Name], [l5].[OneToMany_Optional_Inverse4Id], [l5].[OneToMany_Required_Inverse4Id], [l5].[OneToOne_Optional_PK_Inverse4Id], [l5].[PeriodEnd], [l5].[PeriodStart], [t3].[Id] AS [Id0], [t3].[Id0] AS [Id00], [t3].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN ( + SELECT [l6].[Id], [t4].[Id] AS [Id0], [t4].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] + INNER JOIN ( + SELECT [l7].[Id], [l8].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] ON [l7].[Id] = [l8].[Id] + WHERE [l7].[OneToOne_Required_PK_Date] IS NOT NULL AND [l7].[Level1_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t4] ON [l6].[Id] = [t4].[Id] + WHERE [l6].[Level2_Required_Id] IS NOT NULL AND [l6].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t3] ON [l5].[Id] = [t3].[Id] + WHERE [l5].[Level3_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse4Id] IS NOT NULL +) AS [t2] ON CASE + WHEN [t0].[Level2_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [t0].[Id] +END = [t2].[Level3_Required_Id] +LEFT JOIN ( + SELECT [l9].[Id], [l9].[Level3_Optional_Id], [l9].[Level3_Required_Id], [l9].[Level4_Name], [l9].[OneToMany_Optional_Inverse4Id], [l9].[OneToMany_Required_Inverse4Id], [l9].[OneToOne_Optional_PK_Inverse4Id], [l9].[PeriodEnd], [l9].[PeriodStart], [t6].[Id] AS [Id0], [t6].[Id0] AS [Id00], [t6].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l9] + INNER JOIN ( + SELECT [l10].[Id], [t7].[Id] AS [Id0], [t7].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l10] + INNER JOIN ( + SELECT [l11].[Id], [l12].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l11] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l12] ON [l11].[Id] = [l12].[Id] + WHERE [l11].[OneToOne_Required_PK_Date] IS NOT NULL AND [l11].[Level1_Required_Id] IS NOT NULL AND [l11].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t7] ON [l10].[Id] = [t7].[Id] + WHERE [l10].[Level2_Required_Id] IS NOT NULL AND [l10].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t6] ON [l9].[Id] = [t6].[Id] + WHERE [l9].[Level3_Required_Id] IS NOT NULL AND [l9].[OneToMany_Required_Inverse4Id] IS NOT NULL +) AS [t5] ON CASE + WHEN [t0].[Level2_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [t0].[Id] +END = [t5].[OneToMany_Optional_Inverse4Id] +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0], [t0].[Id00], [t2].[Id], [t2].[Id0], [t2].[Id00], [t2].[Id000], [t5].[Id], [t5].[Id0], [t5].[Id00]"); + } + + public override async Task Multi_level_include_correct_PK_is_chosen_as_the_join_predicate_for_queries_that_join_same_table_multiple_times(bool async) + { + await base.Multi_level_include_correct_PK_is_chosen_as_the_join_predicate_for_queries_that_join_same_table_multiple_times(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t4].[Id], [t4].[OneToOne_Required_PK_Date], [t4].[Level1_Optional_Id], [t4].[Level1_Required_Id], [t4].[Level2_Name], [t4].[OneToMany_Optional_Inverse2Id], [t4].[OneToMany_Required_Inverse2Id], [t4].[OneToOne_Optional_PK_Inverse2Id], [t4].[PeriodEnd], [t4].[PeriodStart], [t4].[Id0], [t4].[Id1], [t4].[Level2_Optional_Id], [t4].[Level2_Required_Id], [t4].[Level3_Name], [t4].[OneToMany_Optional_Inverse3Id], [t4].[OneToMany_Required_Inverse3Id], [t4].[OneToOne_Optional_PK_Inverse3Id], [t4].[PeriodEnd0], [t4].[PeriodStart0], [t4].[Id00], [t4].[OneToOne_Required_PK_Date0], [t4].[Level1_Optional_Id0], [t4].[Level1_Required_Id0], [t4].[Level2_Name0], [t4].[OneToMany_Optional_Inverse2Id0], [t4].[OneToMany_Required_Inverse2Id0], [t4].[OneToOne_Optional_PK_Inverse2Id0], [t4].[PeriodEnd00], [t4].[PeriodStart00], [t4].[Id10], [t4].[Id000], [t4].[Id01], [t4].[Id2], [t4].[Level2_Optional_Id0], [t4].[Level2_Required_Id0], [t4].[Level3_Name0], [t4].[OneToMany_Optional_Inverse3Id0], [t4].[OneToMany_Required_Inverse3Id0], [t4].[OneToOne_Optional_PK_Inverse3Id0], [t4].[PeriodEnd1], [t4].[PeriodStart1], [t4].[Id02], [t4].[Id0000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0], [t3].[Id] AS [Id1], [t3].[Level2_Optional_Id], [t3].[Level2_Required_Id], [t3].[Level3_Name], [t3].[OneToMany_Optional_Inverse3Id], [t3].[OneToMany_Required_Inverse3Id], [t3].[OneToOne_Optional_PK_Inverse3Id], [t3].[PeriodEnd] AS [PeriodEnd0], [t3].[PeriodStart] AS [PeriodStart0], [t3].[Id0] AS [Id00], [t3].[OneToOne_Required_PK_Date] AS [OneToOne_Required_PK_Date0], [t3].[Level1_Optional_Id] AS [Level1_Optional_Id0], [t3].[Level1_Required_Id] AS [Level1_Required_Id0], [t3].[Level2_Name] AS [Level2_Name0], [t3].[OneToMany_Optional_Inverse2Id] AS [OneToMany_Optional_Inverse2Id0], [t3].[OneToMany_Required_Inverse2Id] AS [OneToMany_Required_Inverse2Id0], [t3].[OneToOne_Optional_PK_Inverse2Id] AS [OneToOne_Optional_PK_Inverse2Id0], [t3].[PeriodEnd0] AS [PeriodEnd00], [t3].[PeriodStart0] AS [PeriodStart00], [t3].[Id1] AS [Id10], [t3].[Id00] AS [Id000], [t3].[Id01], [t3].[Id2], [t3].[Level2_Optional_Id0], [t3].[Level2_Required_Id0], [t3].[Level3_Name0], [t3].[OneToMany_Optional_Inverse3Id0], [t3].[OneToMany_Required_Inverse3Id0], [t3].[OneToOne_Optional_PK_Inverse3Id0], [t3].[PeriodEnd1], [t3].[PeriodStart1], [t3].[Id02], [t3].[Id000] AS [Id0000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t0].[Id] AS [Id0], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd] AS [PeriodEnd0], [t0].[PeriodStart] AS [PeriodStart0], [t].[Id] AS [Id1], [t].[Id0] AS [Id00], [t0].[Id0] AS [Id01], [t1].[Id] AS [Id2], [t1].[Level2_Optional_Id] AS [Level2_Optional_Id0], [t1].[Level2_Required_Id] AS [Level2_Required_Id0], [t1].[Level3_Name] AS [Level3_Name0], [t1].[OneToMany_Optional_Inverse3Id] AS [OneToMany_Optional_Inverse3Id0], [t1].[OneToMany_Required_Inverse3Id] AS [OneToMany_Required_Inverse3Id0], [t1].[OneToOne_Optional_PK_Inverse3Id] AS [OneToOne_Optional_PK_Inverse3Id0], [t1].[PeriodEnd] AS [PeriodEnd1], [t1].[PeriodStart] AS [PeriodStart1], [t1].[Id0] AS [Id02], [t1].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] ON [l2].[Id] = [t].[Id] + INNER JOIN ( + SELECT [l5].[Id], [l5].[OneToOne_Required_PK_Date], [l5].[Level1_Optional_Id], [l5].[Level1_Required_Id], [l5].[Level2_Name], [l5].[OneToMany_Optional_Inverse2Id], [l5].[OneToMany_Required_Inverse2Id], [l5].[OneToOne_Optional_PK_Inverse2Id], [l5].[PeriodEnd], [l5].[PeriodStart], [l6].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] ON [l5].[Id] = [l6].[Id] + WHERE [l5].[OneToOne_Required_PK_Date] IS NOT NULL AND [l5].[Level1_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t0] ON [l2].[OneToMany_Required_Inverse3Id] = CASE + WHEN [t0].[OneToOne_Required_PK_Date] IS NOT NULL AND [t0].[Level1_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t0].[Id] + END + LEFT JOIN ( + SELECT [l7].[Id], [l7].[Level2_Optional_Id], [l7].[Level2_Required_Id], [l7].[Level3_Name], [l7].[OneToMany_Optional_Inverse3Id], [l7].[OneToMany_Required_Inverse3Id], [l7].[OneToOne_Optional_PK_Inverse3Id], [l7].[PeriodEnd], [l7].[PeriodStart], [t2].[Id] AS [Id0], [t2].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] + INNER JOIN ( + SELECT [l8].[Id], [l9].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l9] ON [l8].[Id] = [l9].[Id] + WHERE [l8].[OneToOne_Required_PK_Date] IS NOT NULL AND [l8].[Level1_Required_Id] IS NOT NULL AND [l8].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t2] ON [l7].[Id] = [t2].[Id] + WHERE [l7].[Level2_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t1] ON CASE + WHEN [t0].[OneToOne_Required_PK_Date] IS NOT NULL AND [t0].[Level1_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t0].[Id] + END = [t1].[OneToMany_Optional_Inverse3Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t3] ON CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END = [t3].[OneToMany_Optional_Inverse3Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t4] ON [l].[Id] = [t4].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t4].[Id], [t4].[Id0], [t4].[Id1], [t4].[Id10], [t4].[Id000], [t4].[Id00], [t4].[Id01], [t4].[Id2], [t4].[Id02]"); + } + + public override async Task Multi_level_include_one_to_many_optional_and_one_to_many_optional_produces_valid_sql(bool async) + { + await base.Multi_level_include_one_to_many_optional_and_one_to_many_optional_produces_valid_sql(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t1].[Id], [t1].[OneToOne_Required_PK_Date], [t1].[Level1_Optional_Id], [t1].[Level1_Required_Id], [t1].[Level2_Name], [t1].[OneToMany_Optional_Inverse2Id], [t1].[OneToMany_Required_Inverse2Id], [t1].[OneToOne_Optional_PK_Inverse2Id], [t1].[PeriodEnd], [t1].[PeriodStart], [t1].[Id0], [t1].[Id1], [t1].[Level2_Optional_Id], [t1].[Level2_Required_Id], [t1].[Level3_Name], [t1].[OneToMany_Optional_Inverse3Id], [t1].[OneToMany_Required_Inverse3Id], [t1].[OneToOne_Optional_PK_Inverse3Id], [t1].[PeriodEnd0], [t1].[PeriodStart0], [t1].[Id00], [t1].[Id000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0], [t0].[Id] AS [Id1], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd] AS [PeriodEnd0], [t0].[PeriodStart] AS [PeriodStart0], [t0].[Id0] AS [Id00], [t0].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t].[Id] AS [Id0], [t].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] ON [l2].[Id] = [t].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t0] ON CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END = [t0].[OneToMany_Optional_Inverse3Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t1] ON [l].[Id] = [t1].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t1].[Id], [t1].[Id0], [t1].[Id1], [t1].[Id00]"); + } + + public override async Task Null_check_in_anonymous_type_projection_should_not_be_removed(bool async) + { + await base.Null_check_in_anonymous_type_projection_should_not_be_removed(async); + + AssertSql( + @"SELECT [l].[Id], [t1].[c], [t1].[Level3_Name], [t1].[Id], [t1].[Id0], [t1].[Id1], [t1].[Id00], [t1].[Id000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT CASE + WHEN [t0].[Level2_Required_Id] IS NULL OR [t0].[OneToMany_Required_Inverse3Id] IS NULL OR CASE + WHEN [t0].[PeriodEnd] IS NOT NULL AND [t0].[PeriodStart] IS NOT NULL THEN [t0].[PeriodEnd] + END IS NULL OR CASE + WHEN [t0].[PeriodEnd] IS NOT NULL AND [t0].[PeriodStart] IS NOT NULL THEN [t0].[PeriodStart] + END IS NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [c], [t0].[Level3_Name], [l0].[Id], [l1].[Id] AS [Id0], [t0].[Id] AS [Id1], [t0].[Id0] AS [Id00], [t0].[Id00] AS [Id000], [l0].[OneToMany_Optional_Inverse2Id] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Required_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t].[Id] AS [Id0], [t].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] ON [l2].[Id] = [t].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t0] ON CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END = [t0].[Level2_Required_Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t1] ON [l].[Id] = [t1].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t1].[Id], [t1].[Id0], [t1].[Id1], [t1].[Id00]"); + } + + public override async Task Null_check_in_Dto_projection_should_not_be_removed(bool async) + { + await base.Null_check_in_Dto_projection_should_not_be_removed(async); + + AssertSql( + @"SELECT [l].[Id], [t1].[c], [t1].[Level3_Name], [t1].[Id], [t1].[Id0], [t1].[Id1], [t1].[Id00], [t1].[Id000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT CASE + WHEN [t0].[Level2_Required_Id] IS NULL OR [t0].[OneToMany_Required_Inverse3Id] IS NULL OR CASE + WHEN [t0].[PeriodEnd] IS NOT NULL AND [t0].[PeriodStart] IS NOT NULL THEN [t0].[PeriodEnd] + END IS NULL OR CASE + WHEN [t0].[PeriodEnd] IS NOT NULL AND [t0].[PeriodStart] IS NOT NULL THEN [t0].[PeriodStart] + END IS NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [c], [t0].[Level3_Name], [l0].[Id], [l1].[Id] AS [Id0], [t0].[Id] AS [Id1], [t0].[Id0] AS [Id00], [t0].[Id00] AS [Id000], [l0].[OneToMany_Optional_Inverse2Id] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Required_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t].[Id] AS [Id0], [t].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] ON [l2].[Id] = [t].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t0] ON CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END = [t0].[Level2_Required_Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t1] ON [l].[Id] = [t1].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t1].[Id], [t1].[Id0], [t1].[Id1], [t1].[Id00]"); + } + + public override async Task Optional_navigation_with_Include_and_order(bool async) + { + await base.Optional_navigation_with_Include_and_order(async); + + AssertSql( + @"SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [l].[Id], [t].[Id0], [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t0].[Id00] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[Level1_Optional_Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END = [t0].[OneToMany_Optional_Inverse3Id] +ORDER BY [t].[Level2_Name], [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0]"); + } + + public override async Task Optional_navigation_with_Include_ThenInclude(bool async) + { + await base.Optional_navigation_with_Include_ThenInclude(async); + + AssertSql( + @"SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [l].[Id], [t].[Id0], [t3].[Id], [t3].[Level2_Optional_Id], [t3].[Level2_Required_Id], [t3].[Level3_Name], [t3].[OneToMany_Optional_Inverse3Id], [t3].[OneToMany_Required_Inverse3Id], [t3].[OneToOne_Optional_PK_Inverse3Id], [t3].[PeriodEnd], [t3].[PeriodStart], [t3].[Id0], [t3].[Level3_Optional_Id], [t3].[Level3_Required_Id], [t3].[Level4_Name], [t3].[OneToMany_Optional_Inverse4Id], [t3].[OneToMany_Required_Inverse4Id], [t3].[OneToOne_Optional_PK_Inverse4Id], [t3].[PeriodEnd0], [t3].[PeriodStart0], [t3].[Id1], [t3].[Id00], [t3].[Id01], [t3].[Id000], [t3].[Id0000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[Level1_Optional_Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Level3_Optional_Id], [t1].[Level3_Required_Id], [t1].[Level4_Name], [t1].[OneToMany_Optional_Inverse4Id], [t1].[OneToMany_Required_Inverse4Id], [t1].[OneToOne_Optional_PK_Inverse4Id], [t1].[PeriodEnd] AS [PeriodEnd0], [t1].[PeriodStart] AS [PeriodStart0], [t0].[Id] AS [Id1], [t0].[Id0] AS [Id00], [t1].[Id0] AS [Id01], [t1].[Id00] AS [Id000], [t1].[Id000] AS [Id0000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t0] ON [l2].[Id] = [t0].[Id] + LEFT JOIN ( + SELECT [l5].[Id], [l5].[Level3_Optional_Id], [l5].[Level3_Required_Id], [l5].[Level4_Name], [l5].[OneToMany_Optional_Inverse4Id], [l5].[OneToMany_Required_Inverse4Id], [l5].[OneToOne_Optional_PK_Inverse4Id], [l5].[PeriodEnd], [l5].[PeriodStart], [t2].[Id] AS [Id0], [t2].[Id0] AS [Id00], [t2].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN ( + SELECT [l6].[Id], [t4].[Id] AS [Id0], [t4].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] + INNER JOIN ( + SELECT [l7].[Id], [l8].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] ON [l7].[Id] = [l8].[Id] + WHERE [l7].[OneToOne_Required_PK_Date] IS NOT NULL AND [l7].[Level1_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t4] ON [l6].[Id] = [t4].[Id] + WHERE [l6].[Level2_Required_Id] IS NOT NULL AND [l6].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t2] ON [l5].[Id] = [t2].[Id] + WHERE [l5].[Level3_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse4Id] IS NOT NULL + ) AS [t1] ON CASE + WHEN [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [l2].[Id] + END = [t1].[Level3_Optional_Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t3] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END = [t3].[OneToMany_Optional_Inverse3Id] +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t3].[Id], [t3].[Id1], [t3].[Id00], [t3].[Id0], [t3].[Id01], [t3].[Id000]"); + } + + public override async Task Optional_navigation_with_order_by_and_Include(bool async) + { + await base.Optional_navigation_with_order_by_and_Include(async); + + AssertSql( + @"SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [l].[Id], [t].[Id0], [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t0].[Id00] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[Level1_Optional_Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END = [t0].[OneToMany_Optional_Inverse3Id] +ORDER BY [t].[Level2_Name], [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0]"); + } + + public override async Task Orderby_SelectMany_with_Include1(bool async) + { + await base.Orderby_SelectMany_with_Include1(async); + + AssertSql( + @"SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [l].[Id], [t].[Id0], [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t0].[Id00] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +INNER JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[OneToMany_Optional_Inverse2Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] +END = [t0].[OneToMany_Optional_Inverse3Id] +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0]"); + } + + public override async Task Projecting_collection_with_FirstOrDefault(bool async) + { + await base.Projecting_collection_with_FirstOrDefault(async); + + AssertSql( + @"SELECT [t].[Id], [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0] +FROM ( + SELECT TOP(1) [l].[Id] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] + WHERE [l].[Id] = 1 +) AS [t] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t0] ON [t].[Id] = [t0].[OneToMany_Optional_Inverse2Id] +ORDER BY [t].[Id], [t0].[Id]"); + } + + public override async Task Project_collection_and_include(bool async) + { + await base.Project_collection_and_include(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0], [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[OneToMany_Optional_Inverse2Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[OneToOne_Required_PK_Date], [l2].[Level1_Optional_Id], [l2].[Level1_Required_Id], [l2].[Level2_Name], [l2].[OneToMany_Optional_Inverse2Id], [l2].[OneToMany_Required_Inverse2Id], [l2].[OneToOne_Optional_PK_Inverse2Id], [l2].[PeriodEnd], [l2].[PeriodStart], [l3].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] ON [l2].[Id] = [l3].[Id] + WHERE [l2].[OneToOne_Required_PK_Date] IS NOT NULL AND [l2].[Level1_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t0] ON [l].[Id] = [t0].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t0].[Id]"); + } + + public override async Task Project_collection_and_root_entity(bool async) + { + await base.Project_collection_and_root_entity(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t].[Id]"); + } + + public override async Task Project_collection_navigation(bool async) + { + await base.Project_collection_navigation(async); + + AssertSql( + @"SELECT [l].[Id], [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t].[Id]"); + } + + public override async Task Project_collection_navigation_composed(bool async) + { + await base.Project_collection_navigation_composed(async); + + AssertSql( + @"SELECT [l].[Id], [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND ([l0].[Level2_Name] <> N'Foo' OR [l0].[Level2_Name] IS NULL) +) AS [t] ON [l].[Id] = [t].[OneToMany_Optional_Inverse2Id] +WHERE [l].[Id] < 3 +ORDER BY [l].[Id], [t].[Id]"); + } + + public override async Task Project_collection_navigation_nested(bool async) + { + await base.Project_collection_navigation_nested(async); + + AssertSql( + @"SELECT [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t0].[Id00] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[Level1_Optional_Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END = [t0].[OneToMany_Optional_Inverse3Id] +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0]"); + } + + public override async Task Project_collection_navigation_nested_anonymous(bool async) + { + await base.Project_collection_navigation_nested_anonymous(async); + + AssertSql( + @"SELECT [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t0].[Id00] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[Level1_Optional_Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END = [t0].[OneToMany_Optional_Inverse3Id] +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0]"); + } + + public override async Task Project_collection_navigation_nested_with_take(bool async) + { + await base.Project_collection_navigation_nested_with_take(async); + + AssertSql( + @"SELECT [l].[Id], [t].[Id], [t].[Id0], [t1].[Id], [t1].[Level2_Optional_Id], [t1].[Level2_Required_Id], [t1].[Level3_Name], [t1].[OneToMany_Optional_Inverse3Id], [t1].[OneToMany_Required_Inverse3Id], [t1].[OneToOne_Optional_PK_Inverse3Id], [t1].[PeriodEnd], [t1].[PeriodStart], [t1].[Id0], [t1].[Id00] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[Level1_Optional_Id] +LEFT JOIN ( + SELECT [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t0].[Id00] + FROM ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t2].[Id] AS [Id0], [t2].[Id0] AS [Id00], ROW_NUMBER() OVER(PARTITION BY [l2].[OneToMany_Optional_Inverse3Id] ORDER BY [l2].[Id], [t2].[Id], [t2].[Id0]) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t2] ON [l2].[Id] = [t2].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t0] + WHERE [t0].[row] <= 50 +) AS [t1] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END = [t1].[OneToMany_Optional_Inverse3Id] +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t1].[Id], [t1].[Id0]"); + } + + public override async Task Project_collection_navigation_using_ef_property(bool async) + { + await base.Project_collection_navigation_using_ef_property(async); + + AssertSql( + @"SELECT [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t0].[Id00] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[Level1_Optional_Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END = [t0].[OneToMany_Optional_Inverse3Id] +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0]"); + } + + public override async Task Project_navigation_and_collection(bool async) + { + await base.Project_navigation_and_collection(async); + + AssertSql( + @"SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [l].[Id], [t].[Id0], [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t0].[Id00] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[Level1_Optional_Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[PeriodEnd] IS NOT NULL AND [t].[PeriodStart] IS NOT NULL THEN [t].[Id] +END = [t0].[OneToMany_Optional_Inverse3Id] +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0]"); + } + + public override async Task SelectMany_navigation_property_followed_by_select_collection_navigation(bool async) + { + await base.SelectMany_navigation_property_followed_by_select_collection_navigation(async); + + AssertSql( + @"SELECT CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] +END, [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t0].[Id00] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +INNER JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Required_Id], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[OneToMany_Optional_Inverse2Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] +END = [t0].[OneToMany_Optional_Inverse3Id] +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0]"); + } + + public override async Task SelectMany_navigation_property_with_include_and_followed_by_select_collection_navigation(bool async) + { + await base.SelectMany_navigation_property_with_include_and_followed_by_select_collection_navigation(async); + + AssertSql( + @"SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [l].[Id], [t].[Id0], [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t0].[Id00], [t2].[Id], [t2].[Level2_Optional_Id], [t2].[Level2_Required_Id], [t2].[Level3_Name], [t2].[OneToMany_Optional_Inverse3Id], [t2].[OneToMany_Required_Inverse3Id], [t2].[OneToOne_Optional_PK_Inverse3Id], [t2].[PeriodEnd], [t2].[PeriodStart], [t2].[Id0], [t2].[Id00] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +INNER JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[OneToMany_Optional_Inverse2Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] +END = [t0].[OneToMany_Required_Inverse3Id] +LEFT JOIN ( + SELECT [l5].[Id], [l5].[Level2_Optional_Id], [l5].[Level2_Required_Id], [l5].[Level3_Name], [l5].[OneToMany_Optional_Inverse3Id], [l5].[OneToMany_Required_Inverse3Id], [l5].[OneToOne_Optional_PK_Inverse3Id], [l5].[PeriodEnd], [l5].[PeriodStart], [t3].[Id] AS [Id0], [t3].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN ( + SELECT [l6].[Id], [l7].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] ON [l6].[Id] = [l7].[Id] + WHERE [l6].[OneToOne_Required_PK_Date] IS NOT NULL AND [l6].[Level1_Required_Id] IS NOT NULL AND [l6].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t3] ON [l5].[Id] = [t3].[Id] + WHERE [l5].[Level2_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t2] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] +END = [t2].[OneToMany_Optional_Inverse3Id] +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0], [t0].[Id00], [t2].[Id], [t2].[Id0]"); + } + + public override async Task SelectMany_with_Include1(bool async) + { + await base.SelectMany_with_Include1(async); + + AssertSql( + @"SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [l].[Id], [t].[Id0], [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t0].[Id00] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +INNER JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[OneToMany_Optional_Inverse2Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] +END = [t0].[OneToMany_Optional_Inverse3Id] +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0]"); + } + + public override async Task SelectMany_with_Include2(bool async) + { + await base.SelectMany_with_Include2(async); + + AssertSql( + @"SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +INNER JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[OneToMany_Optional_Inverse2Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] +END = [t0].[Level2_Required_Id]"); + } + + public override async Task SelectMany_with_Include_and_order_by(bool async) + { + await base.SelectMany_with_Include_and_order_by(async); + + AssertSql( + @"SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [l].[Id], [t].[Id0], [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t0].[Id00] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +INNER JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[OneToMany_Optional_Inverse2Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] +END = [t0].[OneToMany_Optional_Inverse3Id] +ORDER BY [t].[Level2_Name], [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0]"); + } + + public override async Task SelectMany_with_Include_ThenInclude(bool async) + { + await base.SelectMany_with_Include_ThenInclude(async); + + AssertSql( + @"SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [l].[Id], [t].[Id0], [t0].[Id0], [t0].[Id00], [t2].[Id], [t2].[Level3_Optional_Id], [t2].[Level3_Required_Id], [t2].[Level4_Name], [t2].[OneToMany_Optional_Inverse4Id], [t2].[OneToMany_Required_Inverse4Id], [t2].[OneToOne_Optional_PK_Inverse4Id], [t2].[PeriodEnd], [t2].[PeriodStart], [t2].[Id0], [t2].[Id00], [t2].[Id000] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +INNER JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[OneToMany_Optional_Inverse2Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] +END = [t0].[Level2_Required_Id] +LEFT JOIN ( + SELECT [l5].[Id], [l5].[Level3_Optional_Id], [l5].[Level3_Required_Id], [l5].[Level4_Name], [l5].[OneToMany_Optional_Inverse4Id], [l5].[OneToMany_Required_Inverse4Id], [l5].[OneToOne_Optional_PK_Inverse4Id], [l5].[PeriodEnd], [l5].[PeriodStart], [t3].[Id] AS [Id0], [t3].[Id0] AS [Id00], [t3].[Id00] AS [Id000] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN ( + SELECT [l6].[Id], [t4].[Id] AS [Id0], [t4].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] + INNER JOIN ( + SELECT [l7].[Id], [l8].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] ON [l7].[Id] = [l8].[Id] + WHERE [l7].[OneToOne_Required_PK_Date] IS NOT NULL AND [l7].[Level1_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t4] ON [l6].[Id] = [t4].[Id] + WHERE [l6].[Level2_Required_Id] IS NOT NULL AND [l6].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t3] ON [l5].[Id] = [t3].[Id] + WHERE [l5].[Level3_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse4Id] IS NOT NULL +) AS [t2] ON CASE + WHEN [t0].[Level2_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse3Id] IS NOT NULL AND [t0].[PeriodEnd] IS NOT NULL AND [t0].[PeriodStart] IS NOT NULL THEN [t0].[Id] +END = [t2].[OneToMany_Optional_Inverse4Id] +ORDER BY [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0], [t0].[Id00], [t2].[Id], [t2].[Id0], [t2].[Id00]"); + } + + public override async Task SelectMany_with_navigation_and_Distinct(bool async) + { + await base.SelectMany_with_navigation_and_Distinct(async); + + AssertSql( + @"SELECT [l].[Id], [l].[Date], [l].[Name], [l].[PeriodEnd], [l].[PeriodStart], [t].[Id], [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +INNER JOIN ( + SELECT DISTINCT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[OneToMany_Optional_Inverse2Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[OneToOne_Required_PK_Date], [l2].[Level1_Optional_Id], [l2].[Level1_Required_Id], [l2].[Level2_Name], [l2].[OneToMany_Optional_Inverse2Id], [l2].[OneToMany_Required_Inverse2Id], [l2].[OneToOne_Optional_PK_Inverse2Id], [l2].[PeriodEnd], [l2].[PeriodStart], [l3].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] ON [l2].[Id] = [l3].[Id] + WHERE [l2].[OneToOne_Required_PK_Date] IS NOT NULL AND [l2].[Level1_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t0] ON [l].[Id] = [t0].[OneToMany_Optional_Inverse2Id] +WHERE [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL AND CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[PeriodEnd] +END IS NOT NULL AND CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[PeriodStart] +END IS NOT NULL +ORDER BY [l].[Id], [t].[Id], [t0].[Id]"); + } + + public override async Task SelectMany_with_order_by_and_Include(bool async) + { + await base.SelectMany_with_order_by_and_Include(async); + + AssertSql( + @"SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [l].[Id], [t].[Id0], [t0].[Id], [t0].[Level2_Optional_Id], [t0].[Level2_Required_Id], [t0].[Level3_Name], [t0].[OneToMany_Optional_Inverse3Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[OneToOne_Optional_PK_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0], [t0].[Id00] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +INNER JOIN ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[OneToMany_Optional_Inverse2Id] +LEFT JOIN ( + SELECT [l2].[Id], [l2].[Level2_Optional_Id], [l2].[Level2_Required_Id], [l2].[Level3_Name], [l2].[OneToMany_Optional_Inverse3Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[OneToOne_Optional_PK_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [t1].[Id] AS [Id0], [t1].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t1] ON [l2].[Id] = [t1].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t0] ON CASE + WHEN [t].[OneToOne_Required_PK_Date] IS NOT NULL AND [t].[Level1_Required_Id] IS NOT NULL AND [t].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t].[Id] +END = [t0].[OneToMany_Optional_Inverse3Id] +ORDER BY [t].[Level2_Name], [l].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0]"); + } + + public override async Task Select_nav_prop_collection_one_to_many_required(bool async) + { + await base.Select_nav_prop_collection_one_to_many_required(async); + + AssertSql( + @"SELECT [l].[Id], [t].[c], [t].[Id], [t].[Id0] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END AS [c], [l0].[Id], [l1].[Id] AS [Id0], [l0].[OneToMany_Required_Inverse2Id] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t] ON [l].[Id] = [t].[OneToMany_Required_Inverse2Id] +ORDER BY [l].[Id], [t].[Id]"); + } + + public override async Task Select_subquery_single_nested_subquery(bool async) + { + await base.Select_subquery_single_nested_subquery(async); + + AssertSql( + @"SELECT [l].[Id], [t0].[Id], [t0].[Id0], [t1].[Id], [t1].[Id0], [t1].[Id1], [t1].[Id00], [t0].[c] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [t].[c], [t].[Id], [t].[Id0], [t].[OneToOne_Required_PK_Date], [t].[Level1_Required_Id], [t].[OneToMany_Required_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[OneToMany_Optional_Inverse2Id] + FROM ( + SELECT 1 AS [c], [l0].[Id], [l1].[Id] AS [Id0], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Required_Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l0].[OneToMany_Optional_Inverse2Id], ROW_NUMBER() OVER(PARTITION BY [l0].[OneToMany_Optional_Inverse2Id] ORDER BY CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] + WHERE [t].[row] <= 1 +) AS [t0] ON [l].[Id] = [t0].[OneToMany_Optional_Inverse2Id] +LEFT JOIN ( + SELECT CASE + WHEN [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [l2].[Id] + END AS [Id], [l2].[Id] AS [Id0], [t2].[Id] AS [Id1], [t2].[Id0] AS [Id00], [l2].[OneToMany_Optional_Inverse3Id] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t2] ON [l2].[Id] = [t2].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL +) AS [t1] ON CASE + WHEN [t0].[OneToOne_Required_PK_Date] IS NOT NULL AND [t0].[Level1_Required_Id] IS NOT NULL AND [t0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t0].[Id] +END = [t1].[OneToMany_Optional_Inverse3Id] +ORDER BY [l].[Id], [t0].[Id], [t0].[Id0], [t1].[Id], [t1].[Id0], [t1].[Id1]"); + } + + public override async Task Select_subquery_single_nested_subquery2(bool async) + { + await base.Select_subquery_single_nested_subquery2(async); + + AssertSql( + @"SELECT [l].[Id], [t5].[Id], [t5].[Id0], [t5].[Id1], [t5].[Id00], [t5].[Id000], [t5].[Id2], [t5].[Id01], [t5].[Id10], [t5].[Id001], [t5].[Id0000], [t5].[c] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [l0].[Id], [l1].[Id] AS [Id0], [t1].[Id] AS [Id1], [t1].[Id0] AS [Id00], [t1].[Id00] AS [Id000], [t2].[Id] AS [Id2], [t2].[Id0] AS [Id01], [t2].[Id1] AS [Id10], [t2].[Id00] AS [Id001], [t2].[Id000] AS [Id0000], [t1].[c], CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END AS [c0], [l0].[OneToMany_Optional_Inverse2Id] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + LEFT JOIN ( + SELECT [t0].[c], [t0].[Id], [t0].[Id0], [t0].[Id00], [t0].[Level2_Required_Id], [t0].[OneToMany_Required_Inverse3Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[OneToMany_Optional_Inverse3Id] + FROM ( + SELECT 1 AS [c], [l2].[Id], [t].[Id] AS [Id0], [t].[Id0] AS [Id00], [l2].[Level2_Required_Id], [l2].[OneToMany_Required_Inverse3Id], [l2].[PeriodEnd], [l2].[PeriodStart], [l2].[OneToMany_Optional_Inverse3Id], ROW_NUMBER() OVER(PARTITION BY [l2].[OneToMany_Optional_Inverse3Id] ORDER BY CASE + WHEN [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [l2].[Id] + END) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] + INNER JOIN ( + SELECT [l3].[Id], [l4].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l3] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l4] ON [l3].[Id] = [l4].[Id] + WHERE [l3].[OneToOne_Required_PK_Date] IS NOT NULL AND [l3].[Level1_Required_Id] IS NOT NULL AND [l3].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] ON [l2].[Id] = [t].[Id] + WHERE [l2].[Level2_Required_Id] IS NOT NULL AND [l2].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t0] + WHERE [t0].[row] <= 1 + ) AS [t1] ON CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END = [t1].[OneToMany_Optional_Inverse3Id] + LEFT JOIN ( + SELECT CASE + WHEN [l5].[Level3_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse4Id] IS NOT NULL THEN [l5].[Id] + END AS [Id], [l5].[Id] AS [Id0], [t3].[Id] AS [Id1], [t3].[Id0] AS [Id00], [t3].[Id00] AS [Id000], [l5].[OneToMany_Optional_Inverse4Id] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l5] + INNER JOIN ( + SELECT [l6].[Id], [t4].[Id] AS [Id0], [t4].[Id0] AS [Id00] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l6] + INNER JOIN ( + SELECT [l7].[Id], [l8].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l7] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l8] ON [l7].[Id] = [l8].[Id] + WHERE [l7].[OneToOne_Required_PK_Date] IS NOT NULL AND [l7].[Level1_Required_Id] IS NOT NULL AND [l7].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t4] ON [l6].[Id] = [t4].[Id] + WHERE [l6].[Level2_Required_Id] IS NOT NULL AND [l6].[OneToMany_Required_Inverse3Id] IS NOT NULL + ) AS [t3] ON [l5].[Id] = [t3].[Id] + WHERE [l5].[Level3_Required_Id] IS NOT NULL AND [l5].[OneToMany_Required_Inverse4Id] IS NOT NULL + ) AS [t2] ON CASE + WHEN [t1].[Level2_Required_Id] IS NOT NULL AND [t1].[OneToMany_Required_Inverse3Id] IS NOT NULL THEN [t1].[Id] + END = [t2].[OneToMany_Optional_Inverse4Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL +) AS [t5] ON [l].[Id] = [t5].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t5].[c0], [t5].[Id], [t5].[Id0], [t5].[Id1], [t5].[Id00], [t5].[Id000], [t5].[Id2], [t5].[Id01], [t5].[Id10], [t5].[Id001]"); + } + + public override async Task Skip_on_grouping_element(bool async) + { + await base.Skip_on_grouping_element(async); + + AssertSql( + @"SELECT [t].[Date], [t0].[Id], [t0].[Date], [t0].[Name], [t0].[PeriodEnd], [t0].[PeriodStart] +FROM ( + SELECT [l].[Date] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] + GROUP BY [l].[Date] +) AS [t] +LEFT JOIN ( + SELECT [t1].[Id], [t1].[Date], [t1].[Name], [t1].[PeriodEnd], [t1].[PeriodStart] + FROM ( + SELECT [l0].[Id], [l0].[Date], [l0].[Name], [l0].[PeriodEnd], [l0].[PeriodStart], ROW_NUMBER() OVER(PARTITION BY [l0].[Date] ORDER BY [l0].[Name]) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + ) AS [t1] + WHERE 1 < [t1].[row] +) AS [t0] ON [t].[Date] = [t0].[Date] +ORDER BY [t].[Date], [t0].[Date], [t0].[Name]"); + } + + public override async Task Skip_Take_Distinct_on_grouping_element(bool async) + { + await base.Skip_Take_Distinct_on_grouping_element(async); + + AssertSql( + @"SELECT [t].[Date], [t0].[Id], [t0].[Date], [t0].[Name], [t0].[PeriodEnd], [t0].[PeriodStart] +FROM ( + SELECT [l].[Date] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] + GROUP BY [l].[Date] +) AS [t] +OUTER APPLY ( + SELECT DISTINCT [t1].[Id], [t1].[Date], [t1].[Name], [t1].[PeriodEnd], [t1].[PeriodStart] + FROM ( + SELECT [l0].[Id], [l0].[Date], [l0].[Name], [l0].[PeriodEnd], [l0].[PeriodStart] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + WHERE [t].[Date] = [l0].[Date] + ORDER BY [l0].[Name] + OFFSET 1 ROWS FETCH NEXT 5 ROWS ONLY + ) AS [t1] +) AS [t0] +ORDER BY [t].[Date]"); + } + + public override async Task Skip_Take_on_grouping_element(bool async) + { + await base.Skip_Take_on_grouping_element(async); + + AssertSql( + @"SELECT [t].[Date], [t0].[Id], [t0].[Date], [t0].[Name], [t0].[PeriodEnd], [t0].[PeriodStart] +FROM ( + SELECT [l].[Date] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] + GROUP BY [l].[Date] +) AS [t] +LEFT JOIN ( + SELECT [t1].[Id], [t1].[Date], [t1].[Name], [t1].[PeriodEnd], [t1].[PeriodStart] + FROM ( + SELECT [l0].[Id], [l0].[Date], [l0].[Name], [l0].[PeriodEnd], [l0].[PeriodStart], ROW_NUMBER() OVER(PARTITION BY [l0].[Date] ORDER BY [l0].[Name]) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + ) AS [t1] + WHERE 1 < [t1].[row] AND [t1].[row] <= 6 +) AS [t0] ON [t].[Date] = [t0].[Date] +ORDER BY [t].[Date], [t0].[Date], [t0].[Name]"); + } + + public override async Task Skip_Take_on_grouping_element_inside_collection_projection(bool async) + { + await base.Skip_Take_on_grouping_element_inside_collection_projection(async); + + AssertSql( + @"SELECT [l].[Id], [t2].[Date], [t2].[Id], [t2].[Date0], [t2].[Name], [t2].[PeriodEnd], [t2].[PeriodStart] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +OUTER APPLY ( + SELECT [t].[Date], [t0].[Id], [t0].[Date] AS [Date0], [t0].[Name], [t0].[PeriodEnd], [t0].[PeriodStart] + FROM ( + SELECT [l0].[Date] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + WHERE [l0].[Name] = [l].[Name] OR ([l0].[Name] IS NULL AND [l].[Name] IS NULL) + GROUP BY [l0].[Date] + ) AS [t] + LEFT JOIN ( + SELECT [t1].[Id], [t1].[Date], [t1].[Name], [t1].[PeriodEnd], [t1].[PeriodStart] + FROM ( + SELECT [l1].[Id], [l1].[Date], [l1].[Name], [l1].[PeriodEnd], [l1].[PeriodStart], ROW_NUMBER() OVER(PARTITION BY [l1].[Date] ORDER BY [l1].[Name]) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] + WHERE [l1].[Name] = [l].[Name] OR ([l1].[Name] IS NULL AND [l].[Name] IS NULL) + ) AS [t1] + WHERE 1 < [t1].[row] AND [t1].[row] <= 6 + ) AS [t0] ON [t].[Date] = [t0].[Date] +) AS [t2] +ORDER BY [l].[Id], [t2].[Date], [t2].[Date0], [t2].[Name]"); + } + + public override async Task Skip_Take_on_grouping_element_into_non_entity(bool async) + { + await base.Skip_Take_on_grouping_element_into_non_entity(async); + + AssertSql( + @"SELECT [t].[Date], [t0].[Name], [t0].[Id] +FROM ( + SELECT [l].[Date] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] + GROUP BY [l].[Date] +) AS [t] +LEFT JOIN ( + SELECT [t1].[Name], [t1].[Id], [t1].[Date] + FROM ( + SELECT [l0].[Name], [l0].[Id], [l0].[Date], ROW_NUMBER() OVER(PARTITION BY [l0].[Date] ORDER BY [l0].[Name]) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + ) AS [t1] + WHERE 1 < [t1].[row] AND [t1].[row] <= 6 +) AS [t0] ON [t].[Date] = [t0].[Date] +ORDER BY [t].[Date], [t0].[Date], [t0].[Name]"); + } + + public override async Task Skip_Take_on_grouping_element_with_collection_include(bool async) + { + await base.Skip_Take_on_grouping_element_with_collection_include(async); + + AssertSql( + @"SELECT [t].[Date], [t1].[Id], [t1].[Date], [t1].[Name], [t1].[PeriodEnd], [t1].[PeriodStart], [t1].[Id0], [t1].[OneToOne_Required_PK_Date], [t1].[Level1_Optional_Id], [t1].[Level1_Required_Id], [t1].[Level2_Name], [t1].[OneToMany_Optional_Inverse2Id], [t1].[OneToMany_Required_Inverse2Id], [t1].[OneToOne_Optional_PK_Inverse2Id], [t1].[PeriodEnd0], [t1].[PeriodStart0], [t1].[Id00] +FROM ( + SELECT [l].[Date] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] + GROUP BY [l].[Date] +) AS [t] +OUTER APPLY ( + SELECT [t0].[Id], [t0].[Date], [t0].[Name], [t0].[PeriodEnd], [t0].[PeriodStart], [t2].[Id] AS [Id0], [t2].[OneToOne_Required_PK_Date], [t2].[Level1_Optional_Id], [t2].[Level1_Required_Id], [t2].[Level2_Name], [t2].[OneToMany_Optional_Inverse2Id], [t2].[OneToMany_Required_Inverse2Id], [t2].[OneToOne_Optional_PK_Inverse2Id], [t2].[PeriodEnd] AS [PeriodEnd0], [t2].[PeriodStart] AS [PeriodStart0], [t2].[Id0] AS [Id00] + FROM ( + SELECT [l0].[Id], [l0].[Date], [l0].[Name], [l0].[PeriodEnd], [l0].[PeriodStart] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + WHERE [t].[Date] = [l0].[Date] + ORDER BY [l0].[Name] + OFFSET 1 ROWS FETCH NEXT 5 ROWS ONLY + ) AS [t0] + LEFT JOIN ( + SELECT [l1].[Id], [l1].[OneToOne_Required_PK_Date], [l1].[Level1_Optional_Id], [l1].[Level1_Required_Id], [l1].[Level2_Name], [l1].[OneToMany_Optional_Inverse2Id], [l1].[OneToMany_Required_Inverse2Id], [l1].[OneToOne_Optional_PK_Inverse2Id], [l1].[PeriodEnd], [l1].[PeriodStart], [l2].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] ON [l1].[Id] = [l2].[Id] + WHERE [l1].[OneToOne_Required_PK_Date] IS NOT NULL AND [l1].[Level1_Required_Id] IS NOT NULL AND [l1].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t2] ON [t0].[Id] = [t2].[OneToMany_Optional_Inverse2Id] +) AS [t1] +ORDER BY [t].[Date], [t1].[Name], [t1].[Id], [t1].[Id0]"); + } + + public override async Task Skip_Take_on_grouping_element_with_reference_include(bool async) + { + await base.Skip_Take_on_grouping_element_with_reference_include(async); + + AssertSql( + @"SELECT [t].[Date], [t1].[Id], [t1].[Date], [t1].[Name], [t1].[PeriodEnd], [t1].[PeriodStart], [t1].[Id0], [t1].[OneToOne_Required_PK_Date], [t1].[Level1_Optional_Id], [t1].[Level1_Required_Id], [t1].[Level2_Name], [t1].[OneToMany_Optional_Inverse2Id], [t1].[OneToMany_Required_Inverse2Id], [t1].[OneToOne_Optional_PK_Inverse2Id], [t1].[PeriodEnd0], [t1].[PeriodStart0], [t1].[Id00] +FROM ( + SELECT [l].[Date] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] + GROUP BY [l].[Date] +) AS [t] +OUTER APPLY ( + SELECT [t0].[Id], [t0].[Date], [t0].[Name], [t0].[PeriodEnd], [t0].[PeriodStart], [t2].[Id] AS [Id0], [t2].[OneToOne_Required_PK_Date], [t2].[Level1_Optional_Id], [t2].[Level1_Required_Id], [t2].[Level2_Name], [t2].[OneToMany_Optional_Inverse2Id], [t2].[OneToMany_Required_Inverse2Id], [t2].[OneToOne_Optional_PK_Inverse2Id], [t2].[PeriodEnd] AS [PeriodEnd0], [t2].[PeriodStart] AS [PeriodStart0], [t2].[Id0] AS [Id00] + FROM ( + SELECT [l0].[Id], [l0].[Date], [l0].[Name], [l0].[PeriodEnd], [l0].[PeriodStart] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + WHERE [t].[Date] = [l0].[Date] + ORDER BY [l0].[Name] + OFFSET 1 ROWS FETCH NEXT 5 ROWS ONLY + ) AS [t0] + LEFT JOIN ( + SELECT [l1].[Id], [l1].[OneToOne_Required_PK_Date], [l1].[Level1_Optional_Id], [l1].[Level1_Required_Id], [l1].[Level2_Name], [l1].[OneToMany_Optional_Inverse2Id], [l1].[OneToMany_Required_Inverse2Id], [l1].[OneToOne_Optional_PK_Inverse2Id], [l1].[PeriodEnd], [l1].[PeriodStart], [l2].[Id] AS [Id0] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] ON [l1].[Id] = [l2].[Id] + WHERE [l1].[OneToOne_Required_PK_Date] IS NOT NULL AND [l1].[Level1_Required_Id] IS NOT NULL AND [l1].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t2] ON [t0].[Id] = [t2].[Level1_Optional_Id] +) AS [t1] +ORDER BY [t].[Date], [t1].[Name], [t1].[Id], [t1].[Id0]"); + } + + public override async Task Skip_Take_Select_collection_Skip_Take(bool async) + { + await base.Skip_Take_Select_collection_Skip_Take(async); + + AssertSql( + @"@__p_0='1' + +SELECT [t].[Id], [t].[Name], [t0].[Id], [t0].[Name], [t0].[Level1Id], [t0].[Level2Id], [t0].[Id0], [t0].[Date], [t0].[Name0], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id1], [t0].[Id00] +FROM ( + SELECT [l].[Id], [l].[Name] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] + ORDER BY [l].[Id] + OFFSET @__p_0 ROWS FETCH NEXT @__p_0 ROWS ONLY +) AS [t] +OUTER APPLY ( + SELECT CASE + WHEN [t1].[OneToOne_Required_PK_Date] IS NOT NULL AND [t1].[Level1_Required_Id] IS NOT NULL AND [t1].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t1].[Id] + END AS [Id], [t1].[Level2_Name] AS [Name], [t1].[OneToMany_Required_Inverse2Id] AS [Level1Id], [t1].[Level1_Required_Id] AS [Level2Id], [l1].[Id] AS [Id0], [l1].[Date], [l1].[Name] AS [Name0], [l1].[PeriodEnd], [l1].[PeriodStart], [t1].[Id] AS [Id1], [t1].[Id0] AS [Id00], [t1].[c] + FROM ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Required_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l2].[Id] AS [Id0], CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END AS [c] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] ON [l0].[Id] = [l2].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[Id] = [l0].[OneToMany_Required_Inverse2Id] + ORDER BY CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END + OFFSET 1 ROWS FETCH NEXT 3 ROWS ONLY + ) AS [t1] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [t1].[Level1_Required_Id] = [l1].[Id] +) AS [t0] +ORDER BY [t].[Id], [t0].[c], [t0].[Id1], [t0].[Id00]"); + } + + public override async Task Skip_Take_ToList_on_grouping_element(bool async) + { + await base.Skip_Take_ToList_on_grouping_element(async); + + AssertSql( + @"SELECT [t].[Date], [t0].[Id], [t0].[Date], [t0].[Name], [t0].[PeriodEnd], [t0].[PeriodStart] +FROM ( + SELECT [l].[Date] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] + GROUP BY [l].[Date] +) AS [t] +LEFT JOIN ( + SELECT [t1].[Id], [t1].[Date], [t1].[Name], [t1].[PeriodEnd], [t1].[PeriodStart] + FROM ( + SELECT [l0].[Id], [l0].[Date], [l0].[Name], [l0].[PeriodEnd], [l0].[PeriodStart], ROW_NUMBER() OVER(PARTITION BY [l0].[Date] ORDER BY [l0].[Name]) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + ) AS [t1] + WHERE 1 < [t1].[row] AND [t1].[row] <= 6 +) AS [t0] ON [t].[Date] = [t0].[Date] +ORDER BY [t].[Date], [t0].[Date], [t0].[Name]"); + } + + public override async Task Take_on_correlated_collection_in_projection(bool async) + { + await base.Take_on_correlated_collection_in_projection(async); + + AssertSql( + @"SELECT [l].[Id], [t0].[Id], [t0].[OneToOne_Required_PK_Date], [t0].[Level1_Optional_Id], [t0].[Level1_Required_Id], [t0].[Level2_Name], [t0].[OneToMany_Optional_Inverse2Id], [t0].[OneToMany_Required_Inverse2Id], [t0].[OneToOne_Optional_PK_Inverse2Id], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id0] +FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] +LEFT JOIN ( + SELECT [t].[Id], [t].[OneToOne_Required_PK_Date], [t].[Level1_Optional_Id], [t].[Level1_Required_Id], [t].[Level2_Name], [t].[OneToMany_Optional_Inverse2Id], [t].[OneToMany_Required_Inverse2Id], [t].[OneToOne_Optional_PK_Inverse2Id], [t].[PeriodEnd], [t].[PeriodStart], [t].[Id0] + FROM ( + SELECT [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Optional_Id], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Optional_Inverse2Id], [l0].[OneToMany_Required_Inverse2Id], [l0].[OneToOne_Optional_PK_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l1].[Id] AS [Id0], ROW_NUMBER() OVER(PARTITION BY [l0].[OneToMany_Optional_Inverse2Id] ORDER BY [l0].[Id], [l1].[Id]) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [l0].[Id] = [l1].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL + ) AS [t] + WHERE [t].[row] <= 50 +) AS [t0] ON [l].[Id] = [t0].[OneToMany_Optional_Inverse2Id] +ORDER BY [l].[Id], [t0].[Id]"); + } + + public override async Task Take_on_grouping_element(bool async) + { + await base.Take_on_grouping_element(async); + + AssertSql( + @"SELECT [t].[Date], [t0].[Id], [t0].[Date], [t0].[Name], [t0].[PeriodEnd], [t0].[PeriodStart] +FROM ( + SELECT [l].[Date] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] + GROUP BY [l].[Date] +) AS [t] +LEFT JOIN ( + SELECT [t1].[Id], [t1].[Date], [t1].[Name], [t1].[PeriodEnd], [t1].[PeriodStart] + FROM ( + SELECT [l0].[Id], [l0].[Date], [l0].[Name], [l0].[PeriodEnd], [l0].[PeriodStart], ROW_NUMBER() OVER(PARTITION BY [l0].[Date] ORDER BY [l0].[Name] DESC) AS [row] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + ) AS [t1] + WHERE [t1].[row] <= 10 +) AS [t0] ON [t].[Date] = [t0].[Date] +ORDER BY [t].[Date], [t0].[Date], [t0].[Name] DESC"); + } + + public override async Task Take_Select_collection_Take(bool async) + { + await base.Take_Select_collection_Take(async); + + AssertSql( + @"@__p_0='1' + +SELECT [t].[Id], [t].[Name], [t0].[Id], [t0].[Name], [t0].[Level1Id], [t0].[Level2Id], [t0].[Id0], [t0].[Date], [t0].[Name0], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[Id1], [t0].[Id00] +FROM ( + SELECT TOP(@__p_0) [l].[Id], [l].[Name] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l] + ORDER BY [l].[Id] +) AS [t] +OUTER APPLY ( + SELECT CASE + WHEN [t1].[OneToOne_Required_PK_Date] IS NOT NULL AND [t1].[Level1_Required_Id] IS NOT NULL AND [t1].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [t1].[Id] + END AS [Id], [t1].[Level2_Name] AS [Name], [t1].[OneToMany_Required_Inverse2Id] AS [Level1Id], [t1].[Level1_Required_Id] AS [Level2Id], [l1].[Id] AS [Id0], [l1].[Date], [l1].[Name] AS [Name0], [l1].[PeriodEnd], [l1].[PeriodStart], [t1].[Id] AS [Id1], [t1].[Id0] AS [Id00], [t1].[c] + FROM ( + SELECT TOP(3) [l0].[Id], [l0].[OneToOne_Required_PK_Date], [l0].[Level1_Required_Id], [l0].[Level2_Name], [l0].[OneToMany_Required_Inverse2Id], [l0].[PeriodEnd], [l0].[PeriodStart], [l2].[Id] AS [Id0], CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END AS [c] + FROM [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l0] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l2] ON [l0].[Id] = [l2].[Id] + WHERE [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL AND [t].[Id] = [l0].[OneToMany_Required_Inverse2Id] + ORDER BY CASE + WHEN [l0].[OneToOne_Required_PK_Date] IS NOT NULL AND [l0].[Level1_Required_Id] IS NOT NULL AND [l0].[OneToMany_Required_Inverse2Id] IS NOT NULL THEN [l0].[Id] + END + ) AS [t1] + INNER JOIN [Level1] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [l1] ON [t1].[Level1_Required_Id] = [l1].[Id] +) AS [t0] +ORDER BY [t].[Id], [t0].[c], [t0].[Id1], [t0].[Id00]"); + } + + public override async Task SelectMany_with_predicate_and_DefaultIfEmpty_projecting_root_collection_element_and_another_collection(bool async) + { + var exception = await Assert.ThrowsAsync(() => + base.SelectMany_with_predicate_and_DefaultIfEmpty_projecting_root_collection_element_and_another_collection(async)); + + Assert.Equal( + CoreStrings.ExpressionParameterizationExceptionSensitive( + "Convert(value(Microsoft.EntityFrameworkCore.Query.ComplexNavigationsCollectionsQueryTestBase`1+<>c__DisplayClass140_0[Microsoft.EntityFrameworkCore.Query.TemporalComplexNavigationsSharedTypeQuerySqlServerFixture]).ss.Set(), DbSet`1).TemporalAsOf(1/1/2010 12:00:00 AM)"), + exception.Message); + Assert.True(exception.InnerException is InvalidCastException); + } + + [ConditionalTheory(Skip = "issue #26922")] + public override async Task Filtered_include_include_parameter_used_inside_filter_throws(bool async) + { + await base.Filtered_include_include_parameter_used_inside_filter_throws(async); + + AssertSql(""); + } + + [ConditionalTheory(Skip = "issue #26922")] + public override async Task Filtered_include_outer_parameter_used_inside_filter(bool async) + { + await base.Filtered_include_outer_parameter_used_inside_filter(async); + + AssertSql(""); + } + + [ConditionalTheory(Skip = "issue #26922")] + public override async Task Include_inside_subquery(bool async) + { + await base.Include_inside_subquery(async); + + AssertSql(""); + } + + private void AssertSql(params string[] expected) + => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); +} diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TemporalComplexNavigationsSharedTypeQuerySqlServerFixture.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TemporalComplexNavigationsSharedTypeQuerySqlServerFixture.cs index 60a3bef69bc..821a4ef3033 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TemporalComplexNavigationsSharedTypeQuerySqlServerFixture.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TemporalComplexNavigationsSharedTypeQuerySqlServerFixture.cs @@ -7,12 +7,97 @@ namespace Microsoft.EntityFrameworkCore.Query; public class TemporalComplexNavigationsSharedTypeQuerySqlServerFixture : ComplexNavigationsSharedTypeQuerySqlServerFixture { - protected override string StoreName { get; } = "TemporalComplexNavigationsOwned"; + protected override string StoreName { get; } = "TemporalComplexNavigationsSharedType"; + + public DateTime ChangesDate { get; private set; } protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) { base.OnModelCreating(modelBuilder, context); - modelBuilder.Entity().ToTable(tb => tb.IsTemporal()); + modelBuilder.Entity().ToTable(nameof(Level1), tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("PeriodStart").HasColumnName("PeriodStart"); + ttb.HasPeriodEnd("PeriodEnd").HasColumnName("PeriodEnd"); + })); + } + + protected override void Configure(OwnedNavigationBuilder l2) + { + base.Configure(l2); + + l2.ToTable(nameof(Level1), tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("PeriodStart").HasColumnName("PeriodStart"); + ttb.HasPeriodEnd("PeriodEnd").HasColumnName("PeriodEnd"); + })); + } + + protected override void Configure(OwnedNavigationBuilder l3) + { + base.Configure(l3); + + l3.ToTable(nameof(Level1), tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("PeriodStart").HasColumnName("PeriodStart"); + ttb.HasPeriodEnd("PeriodEnd").HasColumnName("PeriodEnd"); + })); + } + + protected override void Configure(OwnedNavigationBuilder l4) + { + base.Configure(l4); + + l4.ToTable(nameof(Level1), tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("PeriodStart").HasColumnName("PeriodStart"); + ttb.HasPeriodEnd("PeriodEnd").HasColumnName("PeriodEnd"); + })); + } + + protected override void Seed(ComplexNavigationsContext context) + { + base.Seed(context); + + ChangesDate = new DateTime(2010, 1, 1); + + // clean up intermittent history since in the Seed method we do fixup in multiple stages + var tableName = nameof(Level1); + + context.Database.ExecuteSqlRaw($"ALTER TABLE [{tableName}] SET (SYSTEM_VERSIONING = OFF)"); + context.Database.ExecuteSqlRaw($"DELETE FROM [{tableName + "History"}]"); + context.Database.ExecuteSqlRaw($"ALTER TABLE [{tableName}] SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [dbo].[{tableName + "History"}]))"); + + foreach (var entityOne in context.ChangeTracker.Entries().Where(e => e.Entity is Level1).Select(e => e.Entity)) + { + ((Level1)entityOne).Name = ((Level1)entityOne).Name + "Modified"; + } + + foreach (var entityOne in context.ChangeTracker.Entries().Where(e => e.Entity is Level2).Select(e => e.Entity)) + { + ((Level2)entityOne).Name = ((Level2)entityOne).Name + "Modified"; + } + + foreach (var entityOne in context.ChangeTracker.Entries().Where(e => e.Entity is Level3).Select(e => e.Entity)) + { + ((Level3)entityOne).Name = ((Level3)entityOne).Name + "Modified"; + } + + foreach (var entityOne in context.ChangeTracker.Entries().Where(e => e.Entity is Level4).Select(e => e.Entity)) + { + ((Level4)entityOne).Name = ((Level4)entityOne).Name + "Modified"; + } + + context.SaveChanges(); + + context.Database.ExecuteSqlRaw($"ALTER TABLE [{tableName}] SET (SYSTEM_VERSIONING = OFF)"); + context.Database.ExecuteSqlRaw($"ALTER TABLE [{tableName}] DROP PERIOD FOR SYSTEM_TIME"); + + context.Database.ExecuteSqlRaw($"UPDATE [{tableName + "History"}] SET PeriodStart = '2000-01-01T01:00:00.0000000Z'"); + context.Database.ExecuteSqlRaw($"UPDATE [{tableName + "History"}] SET PeriodEnd = '2020-07-01T07:00:00.0000000Z'"); + + context.Database.ExecuteSqlRaw($"ALTER TABLE [{tableName}] ADD PERIOD FOR SYSTEM_TIME ([PeriodStart], [PeriodEnd])"); + context.Database.ExecuteSqlRaw($"ALTER TABLE [{tableName}] SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [dbo].[{tableName + "History"}]))"); } } + diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TemporalOwnedQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TemporalOwnedQuerySqlServerTest.cs new file mode 100644 index 00000000000..c71cc77a64b --- /dev/null +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TemporalOwnedQuerySqlServerTest.cs @@ -0,0 +1,1731 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit.Abstractions; + +namespace Microsoft.EntityFrameworkCore.Query; + +[SqlServerCondition(SqlServerCondition.SupportsTemporalTablesCascadeDelete)] +public class TemporalOwnedQuerySqlServerTest : OwnedQueryRelationalTestBase +{ + public TemporalOwnedQuerySqlServerTest(TemporalOwnedQuerySqlServerFixture fixture, ITestOutputHelper testOutputHelper) + : base(fixture) + { + //Fixture.TestSqlLoggerFactory.SetTestOutputHelper(testOutputHelper); + } + + protected override bool CanExecuteQueryString + => true; + + protected override Expression RewriteServerQueryExpression(Expression serverQueryExpression) + { + var temporalEntityTypes = new List + { + typeof(OwnedPerson), + typeof(Branch), + typeof(LeafA), + typeof(LeafB), + typeof(Barton), + typeof(Star), + typeof(Planet), + typeof(Moon), + }; + + var rewriter = new TemporalPointInTimeQueryRewriter(Fixture.ChangesDate, temporalEntityTypes); + + return rewriter.Visit(serverQueryExpression); + } + + public override async Task Query_with_owned_entity_equality_operator(bool async) + { + await base.Query_with_owned_entity_equality_operator(async); + + AssertSql( + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [t].[Id], [t0].[ClientId], [t0].[Id], [t0].[OrderDate], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[OrderClientId], [t0].[OrderId], [t0].[Id0], [t0].[Detail], [t0].[PeriodEnd0], [t0].[PeriodStart0], [o].[PersonAddress_AddressLine], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +CROSS JOIN ( + SELECT [o0].[Id] + FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + WHERE [o0].[Discriminator] = N'LeafB' +) AS [t] +LEFT JOIN ( + SELECT [o1].[ClientId], [o1].[Id], [o1].[OrderDate], [o1].[PeriodEnd], [o1].[PeriodStart], [o2].[OrderClientId], [o2].[OrderId], [o2].[Id] AS [Id0], [o2].[Detail], [o2].[PeriodEnd] AS [PeriodEnd0], [o2].[PeriodStart] AS [PeriodStart0] + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] + LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o2] ON [o1].[ClientId] = [o2].[OrderClientId] AND [o1].[Id] = [o2].[OrderId] +) AS [t0] ON [o].[Id] = [t0].[ClientId] +WHERE 0 = 1 +ORDER BY [o].[Id], [t].[Id], [t0].[ClientId], [t0].[Id], [t0].[OrderClientId], [t0].[OrderId]"); + } + + public override async Task Query_for_base_type_loads_all_owned_navs(bool async) + { + await base.Query_for_base_type_loads_all_owned_navs(async); + + AssertSql( + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[PeriodEnd], [t].[PeriodStart], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [t].[PeriodEnd0], [t].[PeriodStart0], [o].[PersonAddress_AddressLine], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN ( + SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail], [o1].[PeriodEnd] AS [PeriodEnd0], [o1].[PeriodStart] AS [PeriodStart0] + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +) AS [t] ON [o].[Id] = [t].[ClientId] +ORDER BY [o].[Id], [t].[ClientId], [t].[Id], [t].[OrderClientId], [t].[OrderId]"); + } + + public override async Task No_ignored_include_warning_when_implicit_load(bool async) + { + await base.No_ignored_include_warning_when_implicit_load(async); + + AssertSql( + @"SELECT COUNT(*) +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o]"); + } + + public override async Task Query_for_branch_type_loads_all_owned_navs(bool async) + { + await base.Query_for_branch_type_loads_all_owned_navs(async); + + AssertSql( + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[PeriodEnd], [t].[PeriodStart], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [t].[PeriodEnd0], [t].[PeriodStart0], [o].[PersonAddress_AddressLine], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN ( + SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail], [o1].[PeriodEnd] AS [PeriodEnd0], [o1].[PeriodStart] AS [PeriodStart0] + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +) AS [t] ON [o].[Id] = [t].[ClientId] +WHERE [o].[Discriminator] IN (N'Branch', N'LeafA') +ORDER BY [o].[Id], [t].[ClientId], [t].[Id], [t].[OrderClientId], [t].[OrderId]"); + } + + public override async Task Query_for_branch_type_loads_all_owned_navs_tracking(bool async) + { + await base.Query_for_branch_type_loads_all_owned_navs_tracking(async); + + AssertSql( + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[PeriodEnd], [t].[PeriodStart], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [t].[PeriodEnd0], [t].[PeriodStart0], [o].[PersonAddress_AddressLine], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN ( + SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail], [o1].[PeriodEnd] AS [PeriodEnd0], [o1].[PeriodStart] AS [PeriodStart0] + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +) AS [t] ON [o].[Id] = [t].[ClientId] +WHERE [o].[Discriminator] IN (N'Branch', N'LeafA') +ORDER BY [o].[Id], [t].[ClientId], [t].[Id], [t].[OrderClientId], [t].[OrderId]"); + } + + public override async Task Query_for_leaf_type_loads_all_owned_navs(bool async) + { + await base.Query_for_leaf_type_loads_all_owned_navs(async); + + AssertSql( + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[PeriodEnd], [t].[PeriodStart], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [t].[PeriodEnd0], [t].[PeriodStart0], [o].[PersonAddress_AddressLine], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN ( + SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail], [o1].[PeriodEnd] AS [PeriodEnd0], [o1].[PeriodStart] AS [PeriodStart0] + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +) AS [t] ON [o].[Id] = [t].[ClientId] +WHERE [o].[Discriminator] = N'LeafA' +ORDER BY [o].[Id], [t].[ClientId], [t].[Id], [t].[OrderClientId], [t].[OrderId]"); + } + + public override async Task Query_when_subquery(bool async) + { + await base.Query_when_subquery(async); + + AssertSql( + @"@__p_0='5' + +SELECT [t0].[Id], [t0].[Discriminator], [t0].[Name], [t0].[PeriodEnd], [t0].[PeriodStart], [t1].[ClientId], [t1].[Id], [t1].[OrderDate], [t1].[PeriodEnd], [t1].[PeriodStart], [t1].[OrderClientId], [t1].[OrderId], [t1].[Id0], [t1].[Detail], [t1].[PeriodEnd0], [t1].[PeriodStart0], [t0].[PersonAddress_AddressLine], [t0].[PeriodEnd0], [t0].[PeriodStart0], [t0].[PersonAddress_PlaceType], [t0].[PersonAddress_ZipCode], [t0].[PersonAddress_Country_Name], [t0].[PersonAddress_Country_PlanetId], [t0].[BranchAddress_BranchName], [t0].[BranchAddress_PlaceType], [t0].[BranchAddress_Country_Name], [t0].[BranchAddress_Country_PlanetId], [t0].[LeafBAddress_LeafBType], [t0].[LeafBAddress_PlaceType], [t0].[LeafBAddress_Country_Name], [t0].[LeafBAddress_Country_PlanetId], [t0].[LeafAAddress_LeafType], [t0].[LeafAAddress_PlaceType], [t0].[LeafAAddress_Country_Name], [t0].[LeafAAddress_Country_PlanetId] +FROM ( + SELECT TOP(@__p_0) [t].[Id], [t].[Discriminator], [t].[Name], [t].[PeriodEnd], [t].[PeriodStart], [t].[PersonAddress_AddressLine], [t].[PeriodEnd0], [t].[PeriodStart0], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[PersonAddress_Country_Name], [t].[PersonAddress_Country_PlanetId], [t].[BranchAddress_BranchName], [t].[BranchAddress_PlaceType], [t].[BranchAddress_Country_Name], [t].[BranchAddress_Country_PlanetId], [t].[LeafBAddress_LeafBType], [t].[LeafBAddress_PlaceType], [t].[LeafBAddress_Country_Name], [t].[LeafBAddress_Country_PlanetId], [t].[LeafAAddress_LeafType], [t].[LeafAAddress_PlaceType], [t].[LeafAAddress_Country_Name], [t].[LeafAAddress_Country_PlanetId] + FROM ( + SELECT DISTINCT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_AddressLine], [o].[PeriodEnd] AS [PeriodEnd0], [o].[PeriodStart] AS [PeriodStart0], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] + FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] + ) AS [t] + ORDER BY [t].[Id] +) AS [t0] +LEFT JOIN ( + SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail], [o1].[PeriodEnd] AS [PeriodEnd0], [o1].[PeriodStart] AS [PeriodStart0] + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +) AS [t1] ON [t0].[Id] = [t1].[ClientId] +ORDER BY [t0].[Id], [t1].[ClientId], [t1].[Id], [t1].[OrderClientId], [t1].[OrderId]"); + } + + public override async Task Navigation_rewrite_on_owned_reference_projecting_scalar(bool async) + { + await base.Navigation_rewrite_on_owned_reference_projecting_scalar(async); + + AssertSql( + @"SELECT [o].[PersonAddress_Country_Name] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +WHERE [o].[PersonAddress_Country_Name] = N'USA'"); + } + + public override async Task Navigation_rewrite_on_owned_reference_projecting_entity(bool async) + { + await base.Navigation_rewrite_on_owned_reference_projecting_entity(async); + + AssertSql( + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[PeriodEnd], [t].[PeriodStart], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [t].[PeriodEnd0], [t].[PeriodStart0], [o].[PersonAddress_AddressLine], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN ( + SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail], [o1].[PeriodEnd] AS [PeriodEnd0], [o1].[PeriodStart] AS [PeriodStart0] + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +) AS [t] ON [o].[Id] = [t].[ClientId] +WHERE [o].[PersonAddress_Country_Name] = N'USA' +ORDER BY [o].[Id], [t].[ClientId], [t].[Id], [t].[OrderClientId], [t].[OrderId]"); + } + + public override async Task Navigation_rewrite_on_owned_collection(bool async) + { + await base.Navigation_rewrite_on_owned_collection(async); + + AssertSql( + @"SELECT [o].[Id], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[PeriodEnd], [t].[PeriodStart], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [t].[PeriodEnd0], [t].[PeriodStart0] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN ( + SELECT [o1].[ClientId], [o1].[Id], [o1].[OrderDate], [o1].[PeriodEnd], [o1].[PeriodStart], [o2].[OrderClientId], [o2].[OrderId], [o2].[Id] AS [Id0], [o2].[Detail], [o2].[PeriodEnd] AS [PeriodEnd0], [o2].[PeriodStart] AS [PeriodStart0] + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] + LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o2] ON [o1].[ClientId] = [o2].[OrderClientId] AND [o1].[Id] = [o2].[OrderId] +) AS [t] ON [o].[Id] = [t].[ClientId] +WHERE ( + SELECT COUNT(*) + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + WHERE [o].[Id] = [o0].[ClientId]) > 0 +ORDER BY [o].[Id], [t].[ClientId], [t].[Id], [t].[OrderClientId], [t].[OrderId]"); + } + + public override async Task Navigation_rewrite_on_owned_collection_with_composition(bool async) + { + await base.Navigation_rewrite_on_owned_collection_with_composition(async); + + AssertSql( + @"SELECT COALESCE(( + SELECT TOP(1) CASE + WHEN [o0].[Id] <> 42 THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + WHERE [o].[Id] = [o0].[ClientId] + ORDER BY [o0].[Id]), CAST(0 AS bit)) +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +ORDER BY [o].[Id]"); + } + + public override async Task Navigation_rewrite_on_owned_collection_with_composition_complex(bool async) + { + await base.Navigation_rewrite_on_owned_collection_with_composition_complex(async); + + AssertSql( + @"SELECT ( + SELECT TOP(1) [o1].[PersonAddress_Country_Name] + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + LEFT JOIN [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[Id] + WHERE [o].[Id] = [o0].[ClientId] + ORDER BY [o0].[Id]) +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o]"); + } + + public override async Task SelectMany_on_owned_collection(bool async) + { + await base.SelectMany_on_owned_collection(async); + + AssertSql( + @"SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o].[Id], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id], [o1].[Detail], [o1].[PeriodEnd], [o1].[PeriodStart] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +INNER JOIN [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] ON [o].[Id] = [o0].[ClientId] +LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +ORDER BY [o].[Id], [o0].[ClientId], [o0].[Id], [o1].[OrderClientId], [o1].[OrderId]"); + } + + public override async Task Navigation_rewrite_on_owned_reference_followed_by_regular_entity(bool async) + { + await base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity(async); + + AssertSql( + @"SELECT [p].[Id], [p].[Name], [p].[PeriodEnd], [p].[PeriodStart], [p].[StarId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN [Planet] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [p] ON [o].[PersonAddress_Country_PlanetId] = [p].[Id]"); + } + + public override async Task Filter_owned_entity_chained_with_regular_entity_followed_by_projecting_owned_collection(bool async) + { + await base.Filter_owned_entity_chained_with_regular_entity_followed_by_projecting_owned_collection(async); + + AssertSql( + @"SELECT [o].[Id], [p].[Id], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[PeriodEnd], [t].[PeriodStart], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [t].[PeriodEnd0], [t].[PeriodStart0] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN [Planet] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [p] ON [o].[PersonAddress_Country_PlanetId] = [p].[Id] +LEFT JOIN ( + SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail], [o1].[PeriodEnd] AS [PeriodEnd0], [o1].[PeriodStart] AS [PeriodStart0] + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +) AS [t] ON [o].[Id] = [t].[ClientId] +WHERE [p].[Id] <> 42 OR [p].[Id] IS NULL +ORDER BY [o].[Id], [p].[Id], [t].[ClientId], [t].[Id], [t].[OrderClientId], [t].[OrderId]"); + } + + public override async Task Project_multiple_owned_navigations(bool async) + { + await base.Project_multiple_owned_navigations(async); + + AssertSql( + @"SELECT [o].[Id], [p].[Id], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[PeriodEnd], [t].[PeriodStart], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [t].[PeriodEnd0], [t].[PeriodStart0], [o].[PersonAddress_AddressLine], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [p].[Name], [p].[PeriodEnd], [p].[PeriodStart], [p].[StarId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN [Planet] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [p] ON [o].[PersonAddress_Country_PlanetId] = [p].[Id] +LEFT JOIN ( + SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail], [o1].[PeriodEnd] AS [PeriodEnd0], [o1].[PeriodStart] AS [PeriodStart0] + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +) AS [t] ON [o].[Id] = [t].[ClientId] +ORDER BY [o].[Id], [p].[Id], [t].[ClientId], [t].[Id], [t].[OrderClientId], [t].[OrderId]"); + } + + public override async Task Project_multiple_owned_navigations_with_expansion_on_owned_collections(bool async) + { + await base.Project_multiple_owned_navigations_with_expansion_on_owned_collections(async); + + AssertSql( + @"SELECT ( + SELECT COUNT(*) + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + LEFT JOIN [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[Id] + LEFT JOIN [Planet] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [p0] ON [o1].[PersonAddress_Country_PlanetId] = [p0].[Id] + LEFT JOIN [Star] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [s] ON [p0].[StarId] = [s].[Id] + WHERE [o].[Id] = [o0].[ClientId] AND ([s].[Id] <> 42 OR [s].[Id] IS NULL)) AS [Count], [p].[Id], [p].[Name], [p].[PeriodEnd], [p].[PeriodStart], [p].[StarId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN [Planet] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [p] ON [o].[PersonAddress_Country_PlanetId] = [p].[Id] +ORDER BY [o].[Id]"); + } + + public override async Task Navigation_rewrite_on_owned_reference_followed_by_regular_entity_filter(bool async) + { + await base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_filter(async); + + AssertSql( + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [p].[Id], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[PeriodEnd], [t].[PeriodStart], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [t].[PeriodEnd0], [t].[PeriodStart0], [o].[PersonAddress_AddressLine], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN [Planet] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [p] ON [o].[PersonAddress_Country_PlanetId] = [p].[Id] +LEFT JOIN ( + SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail], [o1].[PeriodEnd] AS [PeriodEnd0], [o1].[PeriodStart] AS [PeriodStart0] + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +) AS [t] ON [o].[Id] = [t].[ClientId] +WHERE [p].[Id] <> 7 OR [p].[Id] IS NULL +ORDER BY [o].[Id], [p].[Id], [t].[ClientId], [t].[Id], [t].[OrderClientId], [t].[OrderId]"); + } + + public override async Task Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_property(bool async) + { + await base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_property(async); + + AssertSql( + @"SELECT [p].[Id] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN [Planet] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [p] ON [o].[PersonAddress_Country_PlanetId] = [p].[Id]"); + } + + public override async Task Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_collection(bool async) + { + await base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_collection(async); + + AssertSql( + @"SELECT [o].[Id], [p].[Id], [m].[Id], [m].[Diameter], [m].[PeriodEnd], [m].[PeriodStart], [m].[PlanetId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN [Planet] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [p] ON [o].[PersonAddress_Country_PlanetId] = [p].[Id] +LEFT JOIN [Moon] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [m] ON [p].[Id] = [m].[PlanetId] +ORDER BY [o].[Id], [p].[Id]"); + } + + public override async Task SelectMany_on_owned_reference_followed_by_regular_entity_and_collection(bool async) + { + await base.SelectMany_on_owned_reference_followed_by_regular_entity_and_collection(async); + + AssertSql( + @"SELECT [m].[Id], [m].[Diameter], [m].[PeriodEnd], [m].[PeriodStart], [m].[PlanetId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN [Planet] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [p] ON [o].[PersonAddress_Country_PlanetId] = [p].[Id] +INNER JOIN [Moon] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [m] ON [p].[Id] = [m].[PlanetId]"); + } + + public override async Task SelectMany_on_owned_reference_with_entity_in_between_ending_in_owned_collection(bool async) + { + await base.SelectMany_on_owned_reference_with_entity_in_between_ending_in_owned_collection(async); + + AssertSql( + @"SELECT [e].[Id], [e].[Name], [e].[PeriodEnd], [e].[PeriodStart], [e].[StarId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN [Planet] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [p] ON [o].[PersonAddress_Country_PlanetId] = [p].[Id] +LEFT JOIN [Star] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [s] ON [p].[StarId] = [s].[Id] +INNER JOIN [Element] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [e] ON [s].[Id] = [e].[StarId]"); + } + + public override async Task Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference(bool async) + { + await base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference(async); + + AssertSql( + @"SELECT [s].[Id], [s].[Name], [s].[PeriodEnd], [s].[PeriodStart], [o].[Id], [p].[Id], [e].[Id], [e].[Name], [e].[PeriodEnd], [e].[PeriodStart], [e].[StarId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN [Planet] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [p] ON [o].[PersonAddress_Country_PlanetId] = [p].[Id] +LEFT JOIN [Star] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [s] ON [p].[StarId] = [s].[Id] +LEFT JOIN [Element] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [e] ON [s].[Id] = [e].[StarId] +ORDER BY [o].[Id], [p].[Id], [s].[Id]"); + } + + public override async Task Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference_and_scalar( + bool async) + { + await base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference_and_scalar(async); + + AssertSql( + @"SELECT [s].[Name] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN [Planet] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [p] ON [o].[PersonAddress_Country_PlanetId] = [p].[Id] +LEFT JOIN [Star] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [s] ON [p].[StarId] = [s].[Id]"); + } + + public override async Task + Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference_in_predicate_and_projection(bool async) + { + await base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference_in_predicate_and_projection( + async); + + AssertSql( + @"SELECT [s].[Id], [s].[Name], [s].[PeriodEnd], [s].[PeriodStart], [o].[Id], [p].[Id], [e].[Id], [e].[Name], [e].[PeriodEnd], [e].[PeriodStart], [e].[StarId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN [Planet] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [p] ON [o].[PersonAddress_Country_PlanetId] = [p].[Id] +LEFT JOIN [Star] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [s] ON [p].[StarId] = [s].[Id] +LEFT JOIN [Element] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [e] ON [s].[Id] = [e].[StarId] +WHERE [s].[Name] = N'Sol' +ORDER BY [o].[Id], [p].[Id], [s].[Id]"); + } + + public override async Task Query_with_OfType_eagerly_loads_correct_owned_navigations(bool async) + { + await base.Query_with_OfType_eagerly_loads_correct_owned_navigations(async); + + AssertSql( + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[PeriodEnd], [t].[PeriodStart], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [t].[PeriodEnd0], [t].[PeriodStart0], [o].[PersonAddress_AddressLine], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN ( + SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail], [o1].[PeriodEnd] AS [PeriodEnd0], [o1].[PeriodStart] AS [PeriodStart0] + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +) AS [t] ON [o].[Id] = [t].[ClientId] +WHERE [o].[Discriminator] = N'LeafA' +ORDER BY [o].[Id], [t].[ClientId], [t].[Id], [t].[OrderClientId], [t].[OrderId]"); + } + + public override async Task Unmapped_property_projection_loads_owned_navigations(bool async) + { + await base.Unmapped_property_projection_loads_owned_navigations(async); + + AssertSql( + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[PeriodEnd], [t].[PeriodStart], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [t].[PeriodEnd0], [t].[PeriodStart0], [o].[PersonAddress_AddressLine], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN ( + SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail], [o1].[PeriodEnd] AS [PeriodEnd0], [o1].[PeriodStart] AS [PeriodStart0] + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +) AS [t] ON [o].[Id] = [t].[ClientId] +WHERE [o].[Id] = 1 +ORDER BY [o].[Id], [t].[ClientId], [t].[Id], [t].[OrderClientId], [t].[OrderId]"); + } + + public override async Task Client_method_skip_loads_owned_navigations(bool async) + { + await base.Client_method_skip_loads_owned_navigations(async); + + AssertSql( + @"@__p_0='1' + +SELECT [t].[Id], [t].[Discriminator], [t].[Name], [t].[PeriodEnd], [t].[PeriodStart], [t0].[ClientId], [t0].[Id], [t0].[OrderDate], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[OrderClientId], [t0].[OrderId], [t0].[Id0], [t0].[Detail], [t0].[PeriodEnd0], [t0].[PeriodStart0], [t].[PersonAddress_AddressLine], [t].[PeriodEnd0], [t].[PeriodStart0], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[PersonAddress_Country_Name], [t].[PersonAddress_Country_PlanetId], [t].[BranchAddress_BranchName], [t].[BranchAddress_PlaceType], [t].[BranchAddress_Country_Name], [t].[BranchAddress_Country_PlanetId], [t].[LeafBAddress_LeafBType], [t].[LeafBAddress_PlaceType], [t].[LeafBAddress_Country_Name], [t].[LeafBAddress_Country_PlanetId], [t].[LeafAAddress_LeafType], [t].[LeafAAddress_PlaceType], [t].[LeafAAddress_Country_Name], [t].[LeafAAddress_Country_PlanetId] +FROM ( + SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_AddressLine], [o].[PeriodEnd] AS [PeriodEnd0], [o].[PeriodStart] AS [PeriodStart0], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] + FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] + ORDER BY [o].[Id] + OFFSET @__p_0 ROWS +) AS [t] +LEFT JOIN ( + SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail], [o1].[PeriodEnd] AS [PeriodEnd0], [o1].[PeriodStart] AS [PeriodStart0] + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +) AS [t0] ON [t].[Id] = [t0].[ClientId] +ORDER BY [t].[Id], [t0].[ClientId], [t0].[Id], [t0].[OrderClientId], [t0].[OrderId]"); + } + + public override async Task Client_method_take_loads_owned_navigations(bool async) + { + await base.Client_method_take_loads_owned_navigations(async); + + AssertSql( + @"@__p_0='2' + +SELECT [t].[Id], [t].[Discriminator], [t].[Name], [t].[PeriodEnd], [t].[PeriodStart], [t0].[ClientId], [t0].[Id], [t0].[OrderDate], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[OrderClientId], [t0].[OrderId], [t0].[Id0], [t0].[Detail], [t0].[PeriodEnd0], [t0].[PeriodStart0], [t].[PersonAddress_AddressLine], [t].[PeriodEnd0], [t].[PeriodStart0], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[PersonAddress_Country_Name], [t].[PersonAddress_Country_PlanetId], [t].[BranchAddress_BranchName], [t].[BranchAddress_PlaceType], [t].[BranchAddress_Country_Name], [t].[BranchAddress_Country_PlanetId], [t].[LeafBAddress_LeafBType], [t].[LeafBAddress_PlaceType], [t].[LeafBAddress_Country_Name], [t].[LeafBAddress_Country_PlanetId], [t].[LeafAAddress_LeafType], [t].[LeafAAddress_PlaceType], [t].[LeafAAddress_Country_Name], [t].[LeafAAddress_Country_PlanetId] +FROM ( + SELECT TOP(@__p_0) [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_AddressLine], [o].[PeriodEnd] AS [PeriodEnd0], [o].[PeriodStart] AS [PeriodStart0], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] + FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] + ORDER BY [o].[Id] +) AS [t] +LEFT JOIN ( + SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail], [o1].[PeriodEnd] AS [PeriodEnd0], [o1].[PeriodStart] AS [PeriodStart0] + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +) AS [t0] ON [t].[Id] = [t0].[ClientId] +ORDER BY [t].[Id], [t0].[ClientId], [t0].[Id], [t0].[OrderClientId], [t0].[OrderId]"); + } + + public override async Task Client_method_skip_take_loads_owned_navigations(bool async) + { + await base.Client_method_skip_take_loads_owned_navigations(async); + + AssertSql( + @"@__p_0='1' +@__p_1='2' + +SELECT [t].[Id], [t].[Discriminator], [t].[Name], [t].[PeriodEnd], [t].[PeriodStart], [t0].[ClientId], [t0].[Id], [t0].[OrderDate], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[OrderClientId], [t0].[OrderId], [t0].[Id0], [t0].[Detail], [t0].[PeriodEnd0], [t0].[PeriodStart0], [t].[PersonAddress_AddressLine], [t].[PeriodEnd0], [t].[PeriodStart0], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[PersonAddress_Country_Name], [t].[PersonAddress_Country_PlanetId], [t].[BranchAddress_BranchName], [t].[BranchAddress_PlaceType], [t].[BranchAddress_Country_Name], [t].[BranchAddress_Country_PlanetId], [t].[LeafBAddress_LeafBType], [t].[LeafBAddress_PlaceType], [t].[LeafBAddress_Country_Name], [t].[LeafBAddress_Country_PlanetId], [t].[LeafAAddress_LeafType], [t].[LeafAAddress_PlaceType], [t].[LeafAAddress_Country_Name], [t].[LeafAAddress_Country_PlanetId] +FROM ( + SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_AddressLine], [o].[PeriodEnd] AS [PeriodEnd0], [o].[PeriodStart] AS [PeriodStart0], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] + FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] + ORDER BY [o].[Id] + OFFSET @__p_0 ROWS FETCH NEXT @__p_1 ROWS ONLY +) AS [t] +LEFT JOIN ( + SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail], [o1].[PeriodEnd] AS [PeriodEnd0], [o1].[PeriodStart] AS [PeriodStart0] + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +) AS [t0] ON [t].[Id] = [t0].[ClientId] +ORDER BY [t].[Id], [t0].[ClientId], [t0].[Id], [t0].[OrderClientId], [t0].[OrderId]"); + } + + public override async Task Client_method_skip_loads_owned_navigations_variation_2(bool async) + { + await base.Client_method_skip_loads_owned_navigations_variation_2(async); + + AssertSql( + @"@__p_0='1' + +SELECT [t].[Id], [t].[Discriminator], [t].[Name], [t].[PeriodEnd], [t].[PeriodStart], [t0].[ClientId], [t0].[Id], [t0].[OrderDate], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[OrderClientId], [t0].[OrderId], [t0].[Id0], [t0].[Detail], [t0].[PeriodEnd0], [t0].[PeriodStart0], [t].[PersonAddress_AddressLine], [t].[PeriodEnd0], [t].[PeriodStart0], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[PersonAddress_Country_Name], [t].[PersonAddress_Country_PlanetId], [t].[BranchAddress_BranchName], [t].[BranchAddress_PlaceType], [t].[BranchAddress_Country_Name], [t].[BranchAddress_Country_PlanetId], [t].[LeafBAddress_LeafBType], [t].[LeafBAddress_PlaceType], [t].[LeafBAddress_Country_Name], [t].[LeafBAddress_Country_PlanetId], [t].[LeafAAddress_LeafType], [t].[LeafAAddress_PlaceType], [t].[LeafAAddress_Country_Name], [t].[LeafAAddress_Country_PlanetId] +FROM ( + SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_AddressLine], [o].[PeriodEnd] AS [PeriodEnd0], [o].[PeriodStart] AS [PeriodStart0], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] + FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] + ORDER BY [o].[Id] + OFFSET @__p_0 ROWS +) AS [t] +LEFT JOIN ( + SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail], [o1].[PeriodEnd] AS [PeriodEnd0], [o1].[PeriodStart] AS [PeriodStart0] + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +) AS [t0] ON [t].[Id] = [t0].[ClientId] +ORDER BY [t].[Id], [t0].[ClientId], [t0].[Id], [t0].[OrderClientId], [t0].[OrderId]"); + } + + public override async Task Client_method_take_loads_owned_navigations_variation_2(bool async) + { + await base.Client_method_take_loads_owned_navigations_variation_2(async); + + AssertSql( + @"@__p_0='2' + +SELECT [t].[Id], [t].[Discriminator], [t].[Name], [t].[PeriodEnd], [t].[PeriodStart], [t0].[ClientId], [t0].[Id], [t0].[OrderDate], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[OrderClientId], [t0].[OrderId], [t0].[Id0], [t0].[Detail], [t0].[PeriodEnd0], [t0].[PeriodStart0], [t].[PersonAddress_AddressLine], [t].[PeriodEnd0], [t].[PeriodStart0], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[PersonAddress_Country_Name], [t].[PersonAddress_Country_PlanetId], [t].[BranchAddress_BranchName], [t].[BranchAddress_PlaceType], [t].[BranchAddress_Country_Name], [t].[BranchAddress_Country_PlanetId], [t].[LeafBAddress_LeafBType], [t].[LeafBAddress_PlaceType], [t].[LeafBAddress_Country_Name], [t].[LeafBAddress_Country_PlanetId], [t].[LeafAAddress_LeafType], [t].[LeafAAddress_PlaceType], [t].[LeafAAddress_Country_Name], [t].[LeafAAddress_Country_PlanetId] +FROM ( + SELECT TOP(@__p_0) [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_AddressLine], [o].[PeriodEnd] AS [PeriodEnd0], [o].[PeriodStart] AS [PeriodStart0], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] + FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] + ORDER BY [o].[Id] +) AS [t] +LEFT JOIN ( + SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail], [o1].[PeriodEnd] AS [PeriodEnd0], [o1].[PeriodStart] AS [PeriodStart0] + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +) AS [t0] ON [t].[Id] = [t0].[ClientId] +ORDER BY [t].[Id], [t0].[ClientId], [t0].[Id], [t0].[OrderClientId], [t0].[OrderId]"); + } + + public override async Task Client_method_skip_take_loads_owned_navigations_variation_2(bool async) + { + await base.Client_method_skip_take_loads_owned_navigations_variation_2(async); + + AssertSql( + @"@__p_0='1' +@__p_1='2' + +SELECT [t].[Id], [t].[Discriminator], [t].[Name], [t].[PeriodEnd], [t].[PeriodStart], [t0].[ClientId], [t0].[Id], [t0].[OrderDate], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[OrderClientId], [t0].[OrderId], [t0].[Id0], [t0].[Detail], [t0].[PeriodEnd0], [t0].[PeriodStart0], [t].[PersonAddress_AddressLine], [t].[PeriodEnd0], [t].[PeriodStart0], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[PersonAddress_Country_Name], [t].[PersonAddress_Country_PlanetId], [t].[BranchAddress_BranchName], [t].[BranchAddress_PlaceType], [t].[BranchAddress_Country_Name], [t].[BranchAddress_Country_PlanetId], [t].[LeafBAddress_LeafBType], [t].[LeafBAddress_PlaceType], [t].[LeafBAddress_Country_Name], [t].[LeafBAddress_Country_PlanetId], [t].[LeafAAddress_LeafType], [t].[LeafAAddress_PlaceType], [t].[LeafAAddress_Country_Name], [t].[LeafAAddress_Country_PlanetId] +FROM ( + SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_AddressLine], [o].[PeriodEnd] AS [PeriodEnd0], [o].[PeriodStart] AS [PeriodStart0], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] + FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] + ORDER BY [o].[Id] + OFFSET @__p_0 ROWS FETCH NEXT @__p_1 ROWS ONLY +) AS [t] +LEFT JOIN ( + SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail], [o1].[PeriodEnd] AS [PeriodEnd0], [o1].[PeriodStart] AS [PeriodStart0] + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +) AS [t0] ON [t].[Id] = [t0].[ClientId] +ORDER BY [t].[Id], [t0].[ClientId], [t0].[Id], [t0].[OrderClientId], [t0].[OrderId]"); + } + + public override async Task Where_owned_collection_navigation_ToList_Count(bool async) + { + await base.Where_owned_collection_navigation_ToList_Count(async); + + AssertSql( + @"SELECT [o].[Id], [o0].[ClientId], [o0].[Id], [o2].[OrderClientId], [o2].[OrderId], [o2].[Id], [o2].[Detail], [o2].[PeriodEnd], [o2].[PeriodStart] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +INNER JOIN [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] ON [o].[Id] = [o0].[ClientId] +LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o2] ON [o0].[ClientId] = [o2].[OrderClientId] AND [o0].[Id] = [o2].[OrderId] +WHERE ( + SELECT COUNT(*) + FROM [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] + WHERE [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId]) = 0 +ORDER BY [o].[Id], [o0].[ClientId], [o0].[Id], [o2].[OrderClientId], [o2].[OrderId]"); + } + + public override async Task Where_collection_navigation_ToArray_Count(bool async) + { + await base.Where_collection_navigation_ToArray_Count(async); + + AssertSql( + @"SELECT [o].[Id], [o0].[ClientId], [o0].[Id], [o2].[OrderClientId], [o2].[OrderId], [o2].[Id], [o2].[Detail], [o2].[PeriodEnd], [o2].[PeriodStart] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +INNER JOIN [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] ON [o].[Id] = [o0].[ClientId] +LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o2] ON [o0].[ClientId] = [o2].[OrderClientId] AND [o0].[Id] = [o2].[OrderId] +WHERE ( + SELECT COUNT(*) + FROM [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] + WHERE [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId]) = 0 +ORDER BY [o].[Id], [o0].[ClientId], [o0].[Id], [o2].[OrderClientId], [o2].[OrderId]"); + } + + public override async Task Where_collection_navigation_AsEnumerable_Count(bool async) + { + await base.Where_collection_navigation_AsEnumerable_Count(async); + + AssertSql( + @"SELECT [o].[Id], [o0].[ClientId], [o0].[Id], [o2].[OrderClientId], [o2].[OrderId], [o2].[Id], [o2].[Detail], [o2].[PeriodEnd], [o2].[PeriodStart] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +INNER JOIN [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] ON [o].[Id] = [o0].[ClientId] +LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o2] ON [o0].[ClientId] = [o2].[OrderClientId] AND [o0].[Id] = [o2].[OrderId] +WHERE ( + SELECT COUNT(*) + FROM [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] + WHERE [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId]) = 0 +ORDER BY [o].[Id], [o0].[ClientId], [o0].[Id], [o2].[OrderClientId], [o2].[OrderId]"); + } + + public override async Task Where_collection_navigation_ToList_Count_member(bool async) + { + await base.Where_collection_navigation_ToList_Count_member(async); + + AssertSql( + @"SELECT [o].[Id], [o0].[ClientId], [o0].[Id], [o2].[OrderClientId], [o2].[OrderId], [o2].[Id], [o2].[Detail], [o2].[PeriodEnd], [o2].[PeriodStart] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +INNER JOIN [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] ON [o].[Id] = [o0].[ClientId] +LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o2] ON [o0].[ClientId] = [o2].[OrderClientId] AND [o0].[Id] = [o2].[OrderId] +WHERE ( + SELECT COUNT(*) + FROM [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] + WHERE [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId]) = 0 +ORDER BY [o].[Id], [o0].[ClientId], [o0].[Id], [o2].[OrderClientId], [o2].[OrderId]"); + } + + public override async Task Where_collection_navigation_ToArray_Length_member(bool async) + { + await base.Where_collection_navigation_ToArray_Length_member(async); + + AssertSql( + @"SELECT [o].[Id], [o0].[ClientId], [o0].[Id], [o2].[OrderClientId], [o2].[OrderId], [o2].[Id], [o2].[Detail], [o2].[PeriodEnd], [o2].[PeriodStart] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +INNER JOIN [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] ON [o].[Id] = [o0].[ClientId] +LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o2] ON [o0].[ClientId] = [o2].[OrderClientId] AND [o0].[Id] = [o2].[OrderId] +WHERE ( + SELECT COUNT(*) + FROM [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] + WHERE [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId]) = 0 +ORDER BY [o].[Id], [o0].[ClientId], [o0].[Id], [o2].[OrderClientId], [o2].[OrderId]"); + } + + public override async Task Can_query_on_indexer_properties(bool async) + { + await base.Can_query_on_indexer_properties(async); + + AssertSql( + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[PeriodEnd], [t].[PeriodStart], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [t].[PeriodEnd0], [t].[PeriodStart0], [o].[PersonAddress_AddressLine], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN ( + SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail], [o1].[PeriodEnd] AS [PeriodEnd0], [o1].[PeriodStart] AS [PeriodStart0] + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +) AS [t] ON [o].[Id] = [t].[ClientId] +WHERE [o].[Name] = N'Mona Cy' +ORDER BY [o].[Id], [t].[ClientId], [t].[Id], [t].[OrderClientId], [t].[OrderId]"); + } + + public override async Task Can_query_on_owned_indexer_properties(bool async) + { + await base.Can_query_on_owned_indexer_properties(async); + + AssertSql( + @"SELECT [o].[Name] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +WHERE [o].[PersonAddress_ZipCode] = 38654"); + } + + public override async Task Can_query_on_indexer_property_when_property_name_from_closure(bool async) + { + await base.Can_query_on_indexer_property_when_property_name_from_closure(async); + + AssertSql( + @"SELECT [o].[Name] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +WHERE [o].[Name] = N'Mona Cy'"); + } + + public override async Task Can_project_indexer_properties(bool async) + { + await base.Can_project_indexer_properties(async); + + AssertSql( + @"SELECT [o].[Name] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o]"); + } + + public override async Task Can_project_owned_indexer_properties(bool async) + { + await base.Can_project_owned_indexer_properties(async); + + AssertSql( + @"SELECT [o].[PersonAddress_AddressLine] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o]"); + } + + public override async Task Can_project_indexer_properties_converted(bool async) + { + await base.Can_project_indexer_properties_converted(async); + + AssertSql( + @"SELECT [o].[Name] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o]"); + } + + public override async Task Can_project_owned_indexer_properties_converted(bool async) + { + await base.Can_project_owned_indexer_properties_converted(async); + + AssertSql( + @"SELECT [o].[PersonAddress_AddressLine] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o]"); + } + + public override async Task Can_OrderBy_indexer_properties(bool async) + { + await base.Can_OrderBy_indexer_properties(async); + + AssertSql( + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[PeriodEnd], [t].[PeriodStart], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [t].[PeriodEnd0], [t].[PeriodStart0], [o].[PersonAddress_AddressLine], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN ( + SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail], [o1].[PeriodEnd] AS [PeriodEnd0], [o1].[PeriodStart] AS [PeriodStart0] + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +) AS [t] ON [o].[Id] = [t].[ClientId] +ORDER BY [o].[Name], [o].[Id], [t].[ClientId], [t].[Id], [t].[OrderClientId], [t].[OrderId]"); + } + + public override async Task Can_OrderBy_indexer_properties_converted(bool async) + { + await base.Can_OrderBy_indexer_properties_converted(async); + + AssertSql( + @"SELECT [o].[Name] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +ORDER BY [o].[Name], [o].[Id]"); + } + + public override async Task Can_OrderBy_owned_indexer_properties(bool async) + { + await base.Can_OrderBy_owned_indexer_properties(async); + + AssertSql( + @"SELECT [o].[Name] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +ORDER BY [o].[PersonAddress_ZipCode], [o].[Id]"); + } + + public override async Task Can_OrderBy_owened_indexer_properties_converted(bool async) + { + await base.Can_OrderBy_owened_indexer_properties_converted(async); + + AssertSql( + @"SELECT [o].[Name] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +ORDER BY [o].[PersonAddress_ZipCode], [o].[Id]"); + } + + public override async Task Can_group_by_indexer_property(bool isAsync) + { + await base.Can_group_by_indexer_property(isAsync); + + AssertSql( + @"SELECT COUNT(*) +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +GROUP BY [o].[Name]"); + } + + public override async Task Can_group_by_converted_indexer_property(bool isAsync) + { + await base.Can_group_by_converted_indexer_property(isAsync); + + AssertSql( + @"SELECT COUNT(*) +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +GROUP BY [o].[Name]"); + } + + public override async Task Can_group_by_owned_indexer_property(bool isAsync) + { + await base.Can_group_by_owned_indexer_property(isAsync); + + AssertSql( + @"SELECT COUNT(*) +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +GROUP BY [o].[PersonAddress_ZipCode]"); + } + + public override async Task Can_group_by_converted_owned_indexer_property(bool isAsync) + { + await base.Can_group_by_converted_owned_indexer_property(isAsync); + + AssertSql( + @"SELECT COUNT(*) +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +GROUP BY [o].[PersonAddress_ZipCode]"); + } + + public override async Task Can_join_on_indexer_property_on_query(bool isAsync) + { + await base.Can_join_on_indexer_property_on_query(isAsync); + + AssertSql( + @"SELECT [o].[Id], [o0].[PersonAddress_Country_Name] AS [Name] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +INNER JOIN [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] ON [o].[PersonAddress_ZipCode] = [o0].[PersonAddress_ZipCode]"); + } + + public override async Task Projecting_indexer_property_ignores_include(bool isAsync) + { + await base.Projecting_indexer_property_ignores_include(isAsync); + + AssertSql( + @"SELECT [o].[PersonAddress_ZipCode] AS [Nation] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o]"); + } + + public override async Task Projecting_indexer_property_ignores_include_converted(bool isAsync) + { + await base.Projecting_indexer_property_ignores_include_converted(isAsync); + + AssertSql( + @"SELECT [o].[PersonAddress_ZipCode] AS [Nation] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o]"); + } + + public override async Task Indexer_property_is_pushdown_into_subquery(bool isAsync) + { + await base.Indexer_property_is_pushdown_into_subquery(isAsync); + + AssertSql( + @"SELECT [o].[Name] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +WHERE ( + SELECT TOP(1) [o0].[Name] + FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + WHERE [o0].[Id] = [o].[Id]) = N'Mona Cy'"); + } + + public override async Task Can_query_indexer_property_on_owned_collection(bool isAsync) + { + await base.Can_query_indexer_property_on_owned_collection(isAsync); + + AssertSql( + @"SELECT [o].[Name] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +WHERE ( + SELECT COUNT(*) + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + WHERE [o].[Id] = [o0].[ClientId] AND DATEPART(year, [o0].[OrderDate]) = 2018) = 1"); + } + + public override async Task Query_for_base_type_loads_all_owned_navs_split(bool async) + { + await base.Query_for_base_type_loads_all_owned_navs_split(async); + + AssertSql( + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_AddressLine], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +ORDER BY [o].[Id]", + // + @"SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o].[Id] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +INNER JOIN [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] ON [o].[Id] = [o0].[ClientId] +ORDER BY [o].[Id], [o0].[ClientId], [o0].[Id]", + // + @"SELECT [o1].[OrderClientId], [o1].[OrderId], [o1].[Id], [o1].[Detail], [o1].[PeriodEnd], [o1].[PeriodStart], [o].[Id], [o0].[ClientId], [o0].[Id] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +INNER JOIN [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] ON [o].[Id] = [o0].[ClientId] +INNER JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +ORDER BY [o].[Id], [o0].[ClientId], [o0].[Id]"); + } + + public override async Task Query_for_branch_type_loads_all_owned_navs_split(bool async) + { + await base.Query_for_branch_type_loads_all_owned_navs_split(async); + + AssertSql( + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_AddressLine], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +WHERE [o].[Discriminator] IN (N'Branch', N'LeafA') +ORDER BY [o].[Id]", + // + @"SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o].[Id] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +INNER JOIN [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] ON [o].[Id] = [o0].[ClientId] +WHERE [o].[Discriminator] IN (N'Branch', N'LeafA') +ORDER BY [o].[Id], [o0].[ClientId], [o0].[Id]", + // + @"SELECT [o1].[OrderClientId], [o1].[OrderId], [o1].[Id], [o1].[Detail], [o1].[PeriodEnd], [o1].[PeriodStart], [o].[Id], [o0].[ClientId], [o0].[Id] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +INNER JOIN [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] ON [o].[Id] = [o0].[ClientId] +INNER JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +WHERE [o].[Discriminator] IN (N'Branch', N'LeafA') +ORDER BY [o].[Id], [o0].[ClientId], [o0].[Id]"); + } + + public override async Task Query_when_subquery_split(bool async) + { + await base.Query_when_subquery_split(async); + + AssertSql( + @"@__p_0='5' + +SELECT TOP(@__p_0) [t].[Id], [t].[Discriminator], [t].[Name], [t].[PeriodEnd], [t].[PeriodStart], [t].[PersonAddress_AddressLine], [t].[PeriodEnd0], [t].[PeriodStart0], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[PersonAddress_Country_Name], [t].[PersonAddress_Country_PlanetId], [t].[BranchAddress_BranchName], [t].[BranchAddress_PlaceType], [t].[BranchAddress_Country_Name], [t].[BranchAddress_Country_PlanetId], [t].[LeafBAddress_LeafBType], [t].[LeafBAddress_PlaceType], [t].[LeafBAddress_Country_Name], [t].[LeafBAddress_Country_PlanetId], [t].[LeafAAddress_LeafType], [t].[LeafAAddress_PlaceType], [t].[LeafAAddress_Country_Name], [t].[LeafAAddress_Country_PlanetId] +FROM ( + SELECT DISTINCT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_AddressLine], [o].[PeriodEnd] AS [PeriodEnd0], [o].[PeriodStart] AS [PeriodStart0], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] + FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +) AS [t] +ORDER BY [t].[Id]", + // + @"@__p_0='5' + +SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [t0].[Id] +FROM ( + SELECT TOP(@__p_0) [t].[Id] + FROM ( + SELECT DISTINCT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_AddressLine], [o].[PeriodEnd] AS [PeriodEnd0], [o].[PeriodStart] AS [PeriodStart0], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] + FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] + ) AS [t] + ORDER BY [t].[Id] +) AS [t0] +INNER JOIN [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] ON [t0].[Id] = [o0].[ClientId] +ORDER BY [t0].[Id], [o0].[ClientId], [o0].[Id]", + // + @"@__p_0='5' + +SELECT [o1].[OrderClientId], [o1].[OrderId], [o1].[Id], [o1].[Detail], [o1].[PeriodEnd], [o1].[PeriodStart], [t0].[Id], [o0].[ClientId], [o0].[Id] +FROM ( + SELECT TOP(@__p_0) [t].[Id] + FROM ( + SELECT DISTINCT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_AddressLine], [o].[PeriodEnd] AS [PeriodEnd0], [o].[PeriodStart] AS [PeriodStart0], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] + FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] + ) AS [t] + ORDER BY [t].[Id] +) AS [t0] +INNER JOIN [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] ON [t0].[Id] = [o0].[ClientId] +INNER JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +ORDER BY [t0].[Id], [o0].[ClientId], [o0].[Id]"); + } + + public override async Task Project_multiple_owned_navigations_split(bool async) + { + await base.Project_multiple_owned_navigations_split(async); + + AssertSql( + @"SELECT [o].[Id], [p].[Id], [o].[PersonAddress_AddressLine], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [p].[Name], [p].[PeriodEnd], [p].[PeriodStart], [p].[StarId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN [Planet] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [p] ON [o].[PersonAddress_Country_PlanetId] = [p].[Id] +ORDER BY [o].[Id], [p].[Id]", + // + @"SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o].[Id], [p].[Id] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN [Planet] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [p] ON [o].[PersonAddress_Country_PlanetId] = [p].[Id] +INNER JOIN [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] ON [o].[Id] = [o0].[ClientId] +ORDER BY [o].[Id], [p].[Id], [o0].[ClientId], [o0].[Id]", + // + @"SELECT [o1].[OrderClientId], [o1].[OrderId], [o1].[Id], [o1].[Detail], [o1].[PeriodEnd], [o1].[PeriodStart], [o].[Id], [p].[Id], [o0].[ClientId], [o0].[Id] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN [Planet] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [p] ON [o].[PersonAddress_Country_PlanetId] = [p].[Id] +INNER JOIN [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] ON [o].[Id] = [o0].[ClientId] +INNER JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +ORDER BY [o].[Id], [p].[Id], [o0].[ClientId], [o0].[Id]"); + } + + public override async Task Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_collection_split(bool async) + { + await base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_collection_split(async); + + AssertSql( + @"SELECT [o].[Id], [p].[Id] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN [Planet] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [p] ON [o].[PersonAddress_Country_PlanetId] = [p].[Id] +ORDER BY [o].[Id], [p].[Id]", + // + @"SELECT [m].[Id], [m].[Diameter], [m].[PeriodEnd], [m].[PeriodStart], [m].[PlanetId], [o].[Id], [p].[Id] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN [Planet] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [p] ON [o].[PersonAddress_Country_PlanetId] = [p].[Id] +INNER JOIN [Moon] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [m] ON [p].[Id] = [m].[PlanetId] +ORDER BY [o].[Id], [p].[Id]"); + } + + public override async Task Query_with_OfType_eagerly_loads_correct_owned_navigations_split(bool async) + { + await base.Query_with_OfType_eagerly_loads_correct_owned_navigations_split(async); + + AssertSql( + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_AddressLine], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +WHERE [o].[Discriminator] = N'LeafA' +ORDER BY [o].[Id]", + // + @"SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o].[Id] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +INNER JOIN [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] ON [o].[Id] = [o0].[ClientId] +WHERE [o].[Discriminator] = N'LeafA' +ORDER BY [o].[Id], [o0].[ClientId], [o0].[Id]", + // + @"SELECT [o1].[OrderClientId], [o1].[OrderId], [o1].[Id], [o1].[Detail], [o1].[PeriodEnd], [o1].[PeriodStart], [o].[Id], [o0].[ClientId], [o0].[Id] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +INNER JOIN [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] ON [o].[Id] = [o0].[ClientId] +INNER JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +WHERE [o].[Discriminator] = N'LeafA' +ORDER BY [o].[Id], [o0].[ClientId], [o0].[Id]"); + } + + public override async Task Unmapped_property_projection_loads_owned_navigations_split(bool async) + { + await base.Unmapped_property_projection_loads_owned_navigations_split(async); + + AssertSql( + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_AddressLine], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +WHERE [o].[Id] = 1 +ORDER BY [o].[Id]", + // + @"SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o].[Id] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +INNER JOIN [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] ON [o].[Id] = [o0].[ClientId] +WHERE [o].[Id] = 1 +ORDER BY [o].[Id], [o0].[ClientId], [o0].[Id]", + // + @"SELECT [o1].[OrderClientId], [o1].[OrderId], [o1].[Id], [o1].[Detail], [o1].[PeriodEnd], [o1].[PeriodStart], [o].[Id], [o0].[ClientId], [o0].[Id] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +INNER JOIN [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] ON [o].[Id] = [o0].[ClientId] +INNER JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +WHERE [o].[Id] = 1 +ORDER BY [o].[Id], [o0].[ClientId], [o0].[Id]"); + } + + public override async Task Can_query_on_indexer_properties_split(bool async) + { + await base.Can_query_on_indexer_properties_split(async); + + AssertSql( + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_AddressLine], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +WHERE [o].[Name] = N'Mona Cy' +ORDER BY [o].[Id]", + // + @"SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o].[Id] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +INNER JOIN [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] ON [o].[Id] = [o0].[ClientId] +WHERE [o].[Name] = N'Mona Cy' +ORDER BY [o].[Id], [o0].[ClientId], [o0].[Id]", + // + @"SELECT [o1].[OrderClientId], [o1].[OrderId], [o1].[Id], [o1].[Detail], [o1].[PeriodEnd], [o1].[PeriodStart], [o].[Id], [o0].[ClientId], [o0].[Id] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +INNER JOIN [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] ON [o].[Id] = [o0].[ClientId] +INNER JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +WHERE [o].[Name] = N'Mona Cy' +ORDER BY [o].[Id], [o0].[ClientId], [o0].[Id]"); + } + + public override async Task GroupBy_with_multiple_aggregates_on_owned_navigation_properties(bool async) + { + await base.GroupBy_with_multiple_aggregates_on_owned_navigation_properties(async); + + AssertSql( + @"SELECT AVG(CAST([s].[Id] AS float)) AS [p1], COALESCE(SUM([s].[Id]), 0) AS [p2], MAX(CAST(LEN([s].[Name]) AS int)) AS [p3] +FROM ( + SELECT 1 AS [Key], [o].[PersonAddress_Country_PlanetId] + FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +) AS [t] +LEFT JOIN [Planet] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [p] ON [t].[PersonAddress_Country_PlanetId] = [p].[Id] +LEFT JOIN [Star] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [s] ON [p].[StarId] = [s].[Id] +GROUP BY [t].[Key]"); + } + + public override async Task Ordering_by_identifying_projection(bool async) + { + await base.Ordering_by_identifying_projection(async); + + AssertSql( + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[PeriodEnd], [t].[PeriodStart], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [t].[PeriodEnd0], [t].[PeriodStart0], [o].[PersonAddress_AddressLine], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN ( + SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail], [o1].[PeriodEnd] AS [PeriodEnd0], [o1].[PeriodStart] AS [PeriodStart0] + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +) AS [t] ON [o].[Id] = [t].[ClientId] +ORDER BY [o].[PersonAddress_PlaceType], [o].[Id], [t].[ClientId], [t].[Id], [t].[OrderClientId], [t].[OrderId]"); + } + + public override async Task Using_from_sql_on_owner_generates_join_with_table_for_owned_shared_dependents(bool async) + { + await base.Using_from_sql_on_owner_generates_join_with_table_for_owned_shared_dependents(async); + + AssertSql( + @"SELECT [m].[Id], [m].[Discriminator], [m].[Name], [m].[PeriodEnd], [m].[PeriodStart], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0], [t2].[Id], [t2].[Id0], [t4].[Id], [t4].[Id0], [t6].[ClientId], [t6].[Id], [t6].[OrderDate], [t6].[PeriodEnd], [t6].[PeriodStart], [t6].[OrderClientId], [t6].[OrderId], [t6].[Id0], [t6].[Detail], [t6].[PeriodEnd0], [t6].[PeriodStart0], [t].[PersonAddress_AddressLine], [t].[PeriodEnd], [t].[PeriodStart], [t].[PersonAddress_PlaceType], [t].[PersonAddress_ZipCode], [t].[Id1], [t].[PersonAddress_Country_Name], [t].[PeriodEnd0], [t].[PeriodStart0], [t].[PersonAddress_Country_PlanetId], [t0].[BranchAddress_BranchName], [t0].[PeriodEnd], [t0].[PeriodStart], [t0].[BranchAddress_PlaceType], [t0].[Id1], [t0].[BranchAddress_Country_Name], [t0].[PeriodEnd0], [t0].[PeriodStart0], [t0].[BranchAddress_Country_PlanetId], [t2].[LeafBAddress_LeafBType], [t2].[PeriodEnd], [t2].[PeriodStart], [t2].[LeafBAddress_PlaceType], [t2].[Id1], [t2].[LeafBAddress_Country_Name], [t2].[PeriodEnd0], [t2].[PeriodStart0], [t2].[LeafBAddress_Country_PlanetId], [t4].[LeafAAddress_LeafType], [t4].[PeriodEnd], [t4].[PeriodStart], [t4].[LeafAAddress_PlaceType], [t4].[Id1], [t4].[LeafAAddress_Country_Name], [t4].[PeriodEnd0], [t4].[PeriodStart0], [t4].[LeafAAddress_Country_PlanetId] +FROM ( + SELECT * FROM ""OwnedPerson"" +) AS [m] +LEFT JOIN ( + SELECT [o].[Id], [o].[PersonAddress_AddressLine], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o0].[Id] AS [Id0], [o].[Id] AS [Id1], [o].[PersonAddress_Country_Name], [o].[PeriodEnd] AS [PeriodEnd0], [o].[PeriodStart] AS [PeriodStart0], [o].[PersonAddress_Country_PlanetId] + FROM [OwnedPerson] AS [o] + INNER JOIN [OwnedPerson] AS [o0] ON [o].[Id] = [o0].[Id] + WHERE [o].[PersonAddress_ZipCode] IS NOT NULL +) AS [t] ON [m].[Id] = CASE + WHEN [t].[PersonAddress_ZipCode] IS NOT NULL THEN [t].[Id] +END +LEFT JOIN ( + SELECT [o1].[Id], [o1].[BranchAddress_BranchName], [o1].[PeriodEnd], [o1].[PeriodStart], [o1].[BranchAddress_PlaceType], [t1].[Id] AS [Id0], [o1].[Id] AS [Id1], [o1].[BranchAddress_Country_Name], [o1].[PeriodEnd] AS [PeriodEnd0], [o1].[PeriodStart] AS [PeriodStart0], [o1].[BranchAddress_Country_PlanetId] + FROM [OwnedPerson] AS [o1] + INNER JOIN ( + SELECT [o2].[Id] + FROM [OwnedPerson] AS [o2] + WHERE [o2].[Discriminator] IN (N'Branch', N'LeafA') + ) AS [t1] ON [o1].[Id] = [t1].[Id] + WHERE [o1].[BranchAddress_BranchName] IS NOT NULL +) AS [t0] ON [m].[Id] = CASE + WHEN [t0].[BranchAddress_BranchName] IS NOT NULL THEN [t0].[Id] +END +LEFT JOIN ( + SELECT [o3].[Id], [o3].[LeafBAddress_LeafBType], [o3].[PeriodEnd], [o3].[PeriodStart], [o3].[LeafBAddress_PlaceType], [t3].[Id] AS [Id0], [o3].[Id] AS [Id1], [o3].[LeafBAddress_Country_Name], [o3].[PeriodEnd] AS [PeriodEnd0], [o3].[PeriodStart] AS [PeriodStart0], [o3].[LeafBAddress_Country_PlanetId] + FROM [OwnedPerson] AS [o3] + INNER JOIN ( + SELECT [o4].[Id] + FROM [OwnedPerson] AS [o4] + WHERE [o4].[Discriminator] = N'LeafB' + ) AS [t3] ON [o3].[Id] = [t3].[Id] + WHERE [o3].[LeafBAddress_LeafBType] IS NOT NULL +) AS [t2] ON [m].[Id] = CASE + WHEN [t2].[LeafBAddress_LeafBType] IS NOT NULL THEN [t2].[Id] +END +LEFT JOIN ( + SELECT [o5].[Id], [o5].[LeafAAddress_LeafType], [o5].[PeriodEnd], [o5].[PeriodStart], [o5].[LeafAAddress_PlaceType], [t5].[Id] AS [Id0], [o5].[Id] AS [Id1], [o5].[LeafAAddress_Country_Name], [o5].[PeriodEnd] AS [PeriodEnd0], [o5].[PeriodStart] AS [PeriodStart0], [o5].[LeafAAddress_Country_PlanetId] + FROM [OwnedPerson] AS [o5] + INNER JOIN ( + SELECT [o6].[Id] + FROM [OwnedPerson] AS [o6] + WHERE [o6].[Discriminator] = N'LeafA' + ) AS [t5] ON [o5].[Id] = [t5].[Id] + WHERE [o5].[LeafAAddress_LeafType] IS NOT NULL +) AS [t4] ON [m].[Id] = CASE + WHEN [t4].[LeafAAddress_LeafType] IS NOT NULL THEN [t4].[Id] +END +LEFT JOIN ( + SELECT [o7].[ClientId], [o7].[Id], [o7].[OrderDate], [o7].[PeriodEnd], [o7].[PeriodStart], [o8].[OrderClientId], [o8].[OrderId], [o8].[Id] AS [Id0], [o8].[Detail], [o8].[PeriodEnd] AS [PeriodEnd0], [o8].[PeriodStart] AS [PeriodStart0] + FROM [Order] AS [o7] + LEFT JOIN [OrderDetail] AS [o8] ON [o7].[ClientId] = [o8].[OrderClientId] AND [o7].[Id] = [o8].[OrderId] +) AS [t6] ON [m].[Id] = [t6].[ClientId] +ORDER BY [m].[Id], [t].[Id], [t].[Id0], [t0].[Id], [t0].[Id0], [t2].[Id], [t2].[Id0], [t4].[Id], [t4].[Id0], [t6].[ClientId], [t6].[Id], [t6].[OrderClientId], [t6].[OrderId]"); + } + + public override async Task Projecting_collection_correlated_with_keyless_entity_after_navigation_works_using_parent_identifiers(bool async) + { + await base.Projecting_collection_correlated_with_keyless_entity_after_navigation_works_using_parent_identifiers(async); + + AssertSql( + @"SELECT [b].[Throned_Value], [f].[Id], [b].[Id], [p].[Id], [p].[Name], [p].[PeriodEnd], [p].[PeriodStart], [p].[StarId] +FROM [Fink] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [f] +LEFT JOIN [Barton] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [b] ON [f].[BartonId] = [b].[Id] +LEFT JOIN [Planet] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [p] ON [b].[Throned_Value] <> [p].[Id] OR [b].[Throned_Value] IS NULL +ORDER BY [f].[Id], [b].[Id]"); + } + + public override async Task Filter_on_indexer_using_closure(bool async) + { + await base.Filter_on_indexer_using_closure(async); + + AssertSql( + @"SELECT [o].[Id], [o].[Discriminator], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart], [t].[ClientId], [t].[Id], [t].[OrderDate], [t].[PeriodEnd], [t].[PeriodStart], [t].[OrderClientId], [t].[OrderId], [t].[Id0], [t].[Detail], [t].[PeriodEnd0], [t].[PeriodStart0], [o].[PersonAddress_AddressLine], [o].[PeriodEnd], [o].[PeriodStart], [o].[PersonAddress_PlaceType], [o].[PersonAddress_ZipCode], [o].[PersonAddress_Country_Name], [o].[PersonAddress_Country_PlanetId], [o].[BranchAddress_BranchName], [o].[BranchAddress_PlaceType], [o].[BranchAddress_Country_Name], [o].[BranchAddress_Country_PlanetId], [o].[LeafBAddress_LeafBType], [o].[LeafBAddress_PlaceType], [o].[LeafBAddress_Country_Name], [o].[LeafBAddress_Country_PlanetId], [o].[LeafAAddress_LeafType], [o].[LeafAAddress_PlaceType], [o].[LeafAAddress_Country_Name], [o].[LeafAAddress_Country_PlanetId] +FROM [OwnedPerson] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o] +LEFT JOIN ( + SELECT [o0].[ClientId], [o0].[Id], [o0].[OrderDate], [o0].[PeriodEnd], [o0].[PeriodStart], [o1].[OrderClientId], [o1].[OrderId], [o1].[Id] AS [Id0], [o1].[Detail], [o1].[PeriodEnd] AS [PeriodEnd0], [o1].[PeriodStart] AS [PeriodStart0] + FROM [Order] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o0] + LEFT JOIN [OrderDetail] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [o1] ON [o0].[ClientId] = [o1].[OrderClientId] AND [o0].[Id] = [o1].[OrderId] +) AS [t] ON [o].[Id] = [t].[ClientId] +WHERE [o].[PersonAddress_ZipCode] = 38654 +ORDER BY [o].[Id], [t].[ClientId], [t].[Id], [t].[OrderClientId], [t].[OrderId]"); + } + + public override async Task Query_loads_reference_nav_automatically_in_projection(bool async) + { + await base.Query_loads_reference_nav_automatically_in_projection(async); + + AssertSql( + @"SELECT TOP(2) [b].[Id], [b].[PeriodEnd], [b].[PeriodStart], [b].[Simple], [b].[Throned_Property], [b].[Throned_Value] +FROM [Fink] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [f] +LEFT JOIN [Barton] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [b] ON [f].[BartonId] = [b].[Id]"); + } + + public override async Task Simple_query_entity_with_owned_collection(bool async) + { + await base.Simple_query_entity_with_owned_collection(async); + + AssertSql( + @"SELECT [s].[Id], [s].[Name], [s].[PeriodEnd], [s].[PeriodStart], [e].[Id], [e].[Name], [e].[PeriodEnd], [e].[PeriodStart], [e].[StarId] +FROM [Star] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [s] +LEFT JOIN [Element] FOR SYSTEM_TIME AS OF '2010-01-01T00:00:00.0000000' AS [e] ON [s].[Id] = [e].[StarId] +ORDER BY [s].[Id]"); + } + + // not AssertQuery so original (non-temporal) query gets executed, but data is modified + // so results don't match expectations + public override Task Owned_entity_without_owner_does_not_throw_for_identity_resolution(bool async, bool useAsTracking) + => Task.CompletedTask; + + public override Task Preserve_includes_when_applying_skip_take_after_anonymous_type_select(bool async) + => Task.CompletedTask; + + public override Task Query_on_collection_entry_works_for_owned_collection(bool async) + => Task.CompletedTask; + + public override Task NoTracking_Include_with_cycles_does_not_throw_when_performing_identity_resolution( + bool async, + bool useAsTracking) + => Task.CompletedTask; + + public override Task Filter_on_indexer_using_function_argument(bool async) + => Task.CompletedTask; + + private void AssertSql(params string[] expected) + => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); + + public class TemporalOwnedQuerySqlServerFixture : RelationalOwnedQueryFixture + { + protected override ITestStoreFactory TestStoreFactory + => SqlServerTestStoreFactory.Instance; + + protected override string StoreName { get; } = "TemporalOwnedQueryTest"; + + public DateTime ChangesDate { get; private set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + modelBuilder.Entity( + eb => + { + eb.ToTable(tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("PeriodStart").HasColumnName("PeriodStart"); + ttb.HasPeriodEnd("PeriodEnd").HasColumnName("PeriodEnd"); + })); + eb.IndexerProperty("Name"); + var ownedPerson = new OwnedPerson { Id = 1 }; + ownedPerson["Name"] = "Mona Cy"; + eb.HasData(ownedPerson); + + eb.OwnsOne( + p => p.PersonAddress, ab => + { + ab.ToTable(tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("PeriodStart").HasColumnName("PeriodStart"); + ttb.HasPeriodEnd("PeriodEnd").HasColumnName("PeriodEnd"); + })); + ab.IndexerProperty("AddressLine"); + ab.IndexerProperty(typeof(int), "ZipCode"); + ab.HasData( + new + { + OwnedPersonId = 1, + PlaceType = "Land", + AddressLine = "804 S. Lakeshore Road", + ZipCode = 38654 + }, + new + { + OwnedPersonId = 2, + PlaceType = "Land", + AddressLine = "7 Church Dr.", + ZipCode = 28655 + }, + new + { + OwnedPersonId = 3, + PlaceType = "Land", + AddressLine = "72 Hickory Rd.", + ZipCode = 07728 + }, + new + { + OwnedPersonId = 4, + PlaceType = "Land", + AddressLine = "28 Strawberry St.", + ZipCode = 19053 + }); + + ab.OwnsOne( + a => a.Country, cb => + { + cb.ToTable(tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("PeriodStart").HasColumnName("PeriodStart"); + ttb.HasPeriodEnd("PeriodEnd").HasColumnName("PeriodEnd"); + })); + cb.HasData( + new + { + OwnedAddressOwnedPersonId = 1, + PlanetId = 1, + Name = "USA" + }, + new + { + OwnedAddressOwnedPersonId = 2, + PlanetId = 1, + Name = "USA" + }, + new + { + OwnedAddressOwnedPersonId = 3, + PlanetId = 1, + Name = "USA" + }, + new + { + OwnedAddressOwnedPersonId = 4, + PlanetId = 1, + Name = "USA" + }); + + cb.HasOne(cc => cc.Planet).WithMany().HasForeignKey(ee => ee.PlanetId) + .OnDelete(DeleteBehavior.Restrict); + }); + }); + + eb.OwnsMany( + p => p.Orders, ob => + { + ob.ToTable(tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("PeriodStart").HasColumnName("PeriodStart"); + ttb.HasPeriodEnd("PeriodEnd").HasColumnName("PeriodEnd"); + })); + ob.IndexerProperty("OrderDate"); + ob.HasData( + new + { + Id = -10, + ClientId = 1, + OrderDate = Convert.ToDateTime("2018-07-11 10:01:41") + }, + new + { + Id = -11, + ClientId = 1, + OrderDate = Convert.ToDateTime("2015-03-03 04:37:59") + }, + new + { + Id = -20, + ClientId = 2, + OrderDate = Convert.ToDateTime("2015-05-25 20:35:48") + }, + new + { + Id = -30, + ClientId = 3, + OrderDate = Convert.ToDateTime("2014-11-10 04:32:42") + }, + new + { + Id = -40, + ClientId = 4, + OrderDate = Convert.ToDateTime("2016-04-25 19:23:56") + } + ); + + ob.OwnsMany(e => e.Details, odb => + { + odb.ToTable(tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("PeriodStart").HasColumnName("PeriodStart"); + ttb.HasPeriodEnd("PeriodEnd").HasColumnName("PeriodEnd"); + })); + odb.HasData( + new + { + Id = -100, + OrderId = -10, + OrderClientId = 1, + Detail = "Discounted Order" + }, + new + { + Id = -101, + OrderId = -10, + OrderClientId = 1, + Detail = "Full Price Order" + }, + new + { + Id = -200, + OrderId = -20, + OrderClientId = 2, + Detail = "Internal Order" + }, + new + { + Id = -300, + OrderId = -30, + OrderClientId = 3, + Detail = "Bulk Order" + }); + }); + }); + }); + + modelBuilder.Entity( + eb => + { + eb.HasData(new { Id = 2, Name = "Antigonus Mitul" }); + + eb.OwnsOne( + p => p.BranchAddress, ab => + { + ab.ToTable(tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("PeriodStart").HasColumnName("PeriodStart"); + ttb.HasPeriodEnd("PeriodEnd").HasColumnName("PeriodEnd"); + })); + ab.IndexerProperty("BranchName").IsRequired(); + ab.HasData( + new + { + BranchId = 2, + PlaceType = "Land", + BranchName = "BranchA" + }, + new + { + BranchId = 3, + PlaceType = "Land", + BranchName = "BranchB" + }); + + ab.OwnsOne( + a => a.Country, cb => + { + cb.ToTable(tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("PeriodStart").HasColumnName("PeriodStart"); + ttb.HasPeriodEnd("PeriodEnd").HasColumnName("PeriodEnd"); + })); + cb.HasData( + new + { + OwnedAddressBranchId = 2, + PlanetId = 1, + Name = "Canada" + }, + new + { + OwnedAddressBranchId = 3, + PlanetId = 1, + Name = "Canada" + }); + }); + }); + }); + + modelBuilder.Entity( + eb => + { + var leafA = new LeafA { Id = 3 }; + leafA["Name"] = "Madalena Morana"; + eb.HasData(leafA); + + eb.OwnsOne( + p => p.LeafAAddress, ab => + { + ab.ToTable(tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("PeriodStart").HasColumnName("PeriodStart"); + ttb.HasPeriodEnd("PeriodEnd").HasColumnName("PeriodEnd"); + })); + ab.IndexerProperty("LeafType"); + + ab.HasData( + new + { + LeafAId = 3, + PlaceType = "Land", + LeafType = 1 + }); + + ab.OwnsOne( + a => a.Country, cb => + { + cb.ToTable(tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("PeriodStart").HasColumnName("PeriodStart"); + ttb.HasPeriodEnd("PeriodEnd").HasColumnName("PeriodEnd"); + })); + cb.HasOne(c => c.Planet).WithMany().HasForeignKey(c => c.PlanetId) + .OnDelete(DeleteBehavior.Restrict); + + cb.HasData( + new + { + OwnedAddressLeafAId = 3, + PlanetId = 1, + Name = "Mexico" + }); + }); + }); + }); + + modelBuilder.Entity( + eb => + { + var leafB = new LeafB { Id = 4 }; + leafB["Name"] = "Vanda Waldemar"; + eb.HasData(leafB); + + eb.OwnsOne( + p => p.LeafBAddress, ab => + { + ab.ToTable(tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("PeriodStart").HasColumnName("PeriodStart"); + ttb.HasPeriodEnd("PeriodEnd").HasColumnName("PeriodEnd"); + })); + ab.IndexerProperty("LeafBType").IsRequired(); + ab.HasData( + new + { + LeafBId = 4, + PlaceType = "Land", + LeafBType = "Green" + }); + + ab.OwnsOne( + a => a.Country, cb => + { + cb.ToTable(tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("PeriodStart").HasColumnName("PeriodStart"); + ttb.HasPeriodEnd("PeriodEnd").HasColumnName("PeriodEnd"); + })); + cb.HasOne(c => c.Planet).WithMany().HasForeignKey(c => c.PlanetId) + .OnDelete(DeleteBehavior.Restrict); + + cb.HasData( + new + { + OwnedAddressLeafBId = 4, + PlanetId = 1, + Name = "Panama" + }); + }); + }); + }); + + modelBuilder.Entity(pb => + { + pb.ToTable(tb => tb.IsTemporal()); + pb.HasData(new Planet { Id = 1, StarId = 1, Name = "Earth" }); + }); + + modelBuilder.Entity(mb => + { + mb.ToTable(tb => tb.IsTemporal()); + mb.HasData( + new Moon + { + Id = 1, + PlanetId = 1, + Diameter = 3474 + }); + }); + + modelBuilder.Entity( + sb => + { + sb.ToTable(tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("PeriodStart").HasColumnName("PeriodStart"); + ttb.HasPeriodEnd("PeriodEnd").HasColumnName("PeriodEnd"); + })); + sb.HasData(new Star { Id = 1, Name = "Sol" }); + sb.OwnsMany( + s => s.Composition, ob => + { + ob.ToTable(tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("PeriodStart").HasColumnName("PeriodStart"); + ttb.HasPeriodEnd("PeriodEnd").HasColumnName("PeriodEnd"); + })); + ob.HasKey(e => e.Id); + ob.HasData( + new + { + Id = "H", + Name = "Hydrogen", + StarId = 1 + }, + new + { + Id = "He", + Name = "Helium", + StarId = 1 + }); + }); + }); + + modelBuilder.Entity( + b => + { + b.ToTable(tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("PeriodStart").HasColumnName("PeriodStart"); + ttb.HasPeriodEnd("PeriodEnd").HasColumnName("PeriodEnd"); + })); + b.OwnsOne( + e => e.Throned, b => + { + b.ToTable(tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("PeriodStart").HasColumnName("PeriodStart"); + ttb.HasPeriodEnd("PeriodEnd").HasColumnName("PeriodEnd"); + })); + b.HasData( + new + { + BartonId = 1, + Property = "Property", + Value = 42 + }); + }); + b.HasData( + new Barton { Id = 1, Simple = "Simple" }, + new Barton { Id = 2, Simple = "Not" }); + }); + + modelBuilder.Entity() + .ToTable(tb => tb.IsTemporal()) + .HasData(new { Id = 1, BartonId = 1 }); + } + + protected override void Seed(PoolableDbContext context) + { + base.Seed(context); + + ChangesDate = new DateTime(2010, 1, 1); + + var ownedPeople = context.Set().AsTracking().ToList(); + foreach (var ownedPerson in ownedPeople) + { + ownedPerson["Name"] = "Modified" + ownedPerson["Name"]; + var orders = ownedPerson.Orders; + foreach (var order in orders) + { + order["OrderDate"] = new DateTime(1000, 1, 1); + var details = order.Details; + foreach (var detail in details) + { + detail.Detail = "Modified" + detail.Detail; + } + } + } + + var stars = context.Set().AsTracking().ToList(); + foreach (var star in stars) + { + star.Name = "Modified" + star.Name; + if (star.Composition.Any()) + { + foreach (var comp in star.Composition) + { + comp.Name = "Modified" + comp.Name; + } + } + } + + var planets = context.Set().AsTracking().ToList(); + foreach (var planet in planets) + { + planet.Name = "Modified" + planet.Name; + } + + var moons = context.Set().AsTracking().ToList(); + foreach (var moon in moons) + { + moon.Diameter += 1000; + } + + var finks = context.Set().AsTracking().ToList(); + context.Set().RemoveRange(finks); + + var bartons = context.Set().Include(x => x.Throned).AsTracking().ToList(); + foreach (var barton in bartons) + { + barton.Simple = "Modified" + barton.Simple; + if (barton.Throned != null) + { + barton.Throned.Property = "Modified" + barton.Throned.Property; + } + } + + context.SaveChanges(); + + var tableNames = new List + { + nameof(Barton), + nameof(Element), + nameof(Fink), + nameof(Moon), + nameof(Order), + nameof(OrderDetail), + nameof(OwnedPerson), + nameof(Planet), + nameof(Star), + }; + + foreach (var tableName in tableNames) + { + context.Database.ExecuteSqlRaw($"ALTER TABLE [{tableName}] SET (SYSTEM_VERSIONING = OFF)"); + context.Database.ExecuteSqlRaw($"ALTER TABLE [{tableName}] DROP PERIOD FOR SYSTEM_TIME"); + + context.Database.ExecuteSqlRaw($"UPDATE [{tableName + "History"}] SET PeriodStart = '2000-01-01T01:00:00.0000000Z'"); + context.Database.ExecuteSqlRaw($"UPDATE [{tableName + "History"}] SET PeriodEnd = '2020-07-01T07:00:00.0000000Z'"); + + context.Database.ExecuteSqlRaw($"ALTER TABLE [{tableName}] ADD PERIOD FOR SYSTEM_TIME ([PeriodStart], [PeriodEnd])"); + context.Database.ExecuteSqlRaw($"ALTER TABLE [{tableName}] SET (SYSTEM_VERSIONING = ON (HISTORY_TABLE = [dbo].[{tableName + "History"}]))"); + } + } + } +} diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TemporalTableSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TemporalTableSqlServerTest.cs new file mode 100644 index 00000000000..91ace13ab4c --- /dev/null +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TemporalTableSqlServerTest.cs @@ -0,0 +1,491 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.EntityFrameworkCore.SqlServer.Internal; +using Microsoft.EntityFrameworkCore.TestModels.TransportationModel; + +namespace Microsoft.EntityFrameworkCore.Query; + +[SqlServerCondition(SqlServerCondition.SupportsTemporalTablesCascadeDelete)] +public class TemporalTableSqlServerTest : NonSharedModelTestBase +{ + protected override string StoreName => "TemporalTableSqlServerTest"; + + protected TestSqlLoggerFactory TestSqlLoggerFactory + => (TestSqlLoggerFactory)ListLoggerFactory; + + protected override ITestStoreFactory TestStoreFactory => SqlServerTestStoreFactory.Instance; + + protected void AssertSql(params string[] expected) => TestSqlLoggerFactory.AssertBaseline(expected); + + [ConditionalTheory] + [InlineData(true)] + [InlineData(false)] + public virtual async Task Temporal_owned_basic(bool async) + { + var contextFactory = await InitializeAsync(); + using (var context = contextFactory.CreateContext()) + { + var date = new DateTime(2000, 1, 1); + + var query = context.MainEntitiesDifferentTable.TemporalAsOf(date); + var _ = async ? await query.ToListAsync() : query.ToList(); + } + + AssertSql( + @"SELECT [m].[Id], [m].[Description], [m].[EndTime], [m].[StartTime], [o].[MainEntityDifferentTableId], [o].[Description], [o].[EndTime], [o].[StartTime] +FROM [MainEntityDifferentTable] FOR SYSTEM_TIME AS OF '2000-01-01T00:00:00.0000000' AS [m] +LEFT JOIN [OwnedEntityDifferentTable] FOR SYSTEM_TIME AS OF '2000-01-01T00:00:00.0000000' AS [o] ON [m].[Id] = [o].[MainEntityDifferentTableId]"); + } + + [ConditionalTheory] + [InlineData(true)] + [InlineData(false)] + public virtual async Task Temporal_owned_join(bool async) + { + var contextFactory = await InitializeAsync(); + using (var context = contextFactory.CreateContext()) + { + var date = new DateTime(2000, 1, 1); + + var query = context.MainEntitiesDifferentTable + .TemporalAsOf(date) + .Join(context.MainEntitiesDifferentTable, o => o.Id, i => i.Id, (o, i) => new { o, i }); + + var _ = async ? await query.ToListAsync() : query.ToList(); + } + + AssertSql( + @"SELECT [m].[Id], [m].[Description], [m].[EndTime], [m].[StartTime], [o].[MainEntityDifferentTableId], [o].[Description], [o].[EndTime], [o].[StartTime], [m0].[Id], [m0].[Description], [m0].[EndTime], [m0].[StartTime], [o0].[MainEntityDifferentTableId], [o0].[Description], [o0].[EndTime], [o0].[StartTime] +FROM [MainEntityDifferentTable] FOR SYSTEM_TIME AS OF '2000-01-01T00:00:00.0000000' AS [m] +INNER JOIN [MainEntityDifferentTable] AS [m0] ON [m].[Id] = [m0].[Id] +LEFT JOIN [OwnedEntityDifferentTable] FOR SYSTEM_TIME AS OF '2000-01-01T00:00:00.0000000' AS [o] ON [m].[Id] = [o].[MainEntityDifferentTableId] +LEFT JOIN [OwnedEntityDifferentTable] AS [o0] ON [m0].[Id] = [o0].[MainEntityDifferentTableId]"); + } + + [ConditionalTheory] + [InlineData(true)] + [InlineData(false)] + public virtual async Task Temporal_owned_set_operation(bool async) + { + var contextFactory = await InitializeAsync(); + using (var context = contextFactory.CreateContext()) + { + var date = new DateTime(2000, 1, 1); + + var query = context.MainEntitiesDifferentTable + .TemporalAsOf(date) + .Union(context.MainEntitiesDifferentTable.TemporalAsOf(date)); + + var _ = async ? await query.ToListAsync() : query.ToList(); + } + + AssertSql( + @"SELECT [t].[Id], [t].[Description], [t].[EndTime], [t].[StartTime], [o].[MainEntityDifferentTableId], [o].[Description], [o].[EndTime], [o].[StartTime] +FROM ( + SELECT [m].[Id], [m].[Description], [m].[EndTime], [m].[StartTime] + FROM [MainEntityDifferentTable] FOR SYSTEM_TIME AS OF '2000-01-01T00:00:00.0000000' AS [m] + UNION + SELECT [m0].[Id], [m0].[Description], [m0].[EndTime], [m0].[StartTime] + FROM [MainEntityDifferentTable] FOR SYSTEM_TIME AS OF '2000-01-01T00:00:00.0000000' AS [m0] +) AS [t] +LEFT JOIN [OwnedEntityDifferentTable] FOR SYSTEM_TIME AS OF '2000-01-01T00:00:00.0000000' AS [o] ON [t].[Id] = [o].[MainEntityDifferentTableId]"); + } + + [ConditionalTheory] + [InlineData(true)] + [InlineData(false)] + public virtual async Task Temporal_owned_FromSql(bool async) + { + var contextFactory = await InitializeAsync(); + using (var context = contextFactory.CreateContext()) + { + var date = new DateTime(2000, 1, 1); + + var query = context.MainEntitiesDifferentTable.FromSqlRaw( + @"SELECT [m].[Id], [m].[Description], [m].[EndTime], [m].[StartTime] +FROM [MainEntityDifferentTable] FOR SYSTEM_TIME AS OF '2000-01-01T00:00:00.0000000' AS [m]"); + + var _ = async ? await query.ToListAsync() : query.ToList(); + } + + // just making sure we don't do anything weird here - there is no way to extract temporal information + // from the FromSql so owned entity will always be treated as a regular query + AssertSql( + @"SELECT [m].[Id], [m].[Description], [m].[EndTime], [m].[StartTime], [o].[MainEntityDifferentTableId], [o].[Description], [o].[EndTime], [o].[StartTime] +FROM ( + SELECT [m].[Id], [m].[Description], [m].[EndTime], [m].[StartTime] + FROM [MainEntityDifferentTable] FOR SYSTEM_TIME AS OF '2000-01-01T00:00:00.0000000' AS [m] +) AS [m] +LEFT JOIN [OwnedEntityDifferentTable] AS [o] ON [m].[Id] = [o].[MainEntityDifferentTableId]"); + } + + [ConditionalTheory] + [InlineData(true)] + [InlineData(false)] + public virtual async Task Temporal_owned_subquery(bool async) + { + var contextFactory = await InitializeAsync(); + using (var context = contextFactory.CreateContext()) + { + var date = new DateTime(2000, 1, 1); + + var query = context.MainEntitiesDifferentTable + .TemporalAsOf(date) + .Distinct() + .OrderByDescending(x => x.Id) + .Take(3); + + var _ = async ? await query.ToListAsync() : query.ToList(); + } + + AssertSql( + @"@__p_0='3' + +SELECT [t0].[Id], [t0].[Description], [t0].[EndTime], [t0].[StartTime], [o].[MainEntityDifferentTableId], [o].[Description], [o].[EndTime], [o].[StartTime] +FROM ( + SELECT TOP(@__p_0) [t].[Id], [t].[Description], [t].[EndTime], [t].[StartTime] + FROM ( + SELECT DISTINCT [m].[Id], [m].[Description], [m].[EndTime], [m].[StartTime] + FROM [MainEntityDifferentTable] FOR SYSTEM_TIME AS OF '2000-01-01T00:00:00.0000000' AS [m] + ) AS [t] + ORDER BY [t].[Id] DESC +) AS [t0] +LEFT JOIN [OwnedEntityDifferentTable] FOR SYSTEM_TIME AS OF '2000-01-01T00:00:00.0000000' AS [o] ON [t0].[Id] = [o].[MainEntityDifferentTableId] +ORDER BY [t0].[Id] DESC"); + } + + [ConditionalTheory] + [InlineData(true)] + [InlineData(false)] + public virtual async Task Temporal_owned_complex(bool async) + { + var contextFactory = await InitializeAsync(); + using (var context = contextFactory.CreateContext()) + { + var date = new DateTime(2000, 1, 1); + + var query = context.MainEntitiesDifferentTable.TemporalAsOf(date) + .Join(context.MainEntitiesDifferentTable, x => x.Id, x => x.Id, (o, i) => new { o, i }) + .Distinct().OrderByDescending(x => x.o.Id).Take(3) + .Join(context.MainEntitiesDifferentTable, xx => xx.o.Id, x => x.Id, (o, i) => new { o, i }); + + var _ = async ? await query.ToListAsync() : query.ToList(); + } + + AssertSql( + @"@__p_0='3' + +SELECT [t0].[Id], [t0].[Description], [t0].[EndTime], [t0].[StartTime], [o].[MainEntityDifferentTableId], [o].[Description], [o].[EndTime], [o].[StartTime], [t0].[Id0], [t0].[Description0], [t0].[EndTime0], [t0].[StartTime0], [o0].[MainEntityDifferentTableId], [o0].[Description], [o0].[EndTime], [o0].[StartTime], [m1].[Id], [m1].[Description], [m1].[EndTime], [m1].[StartTime], [o1].[MainEntityDifferentTableId], [o1].[Description], [o1].[EndTime], [o1].[StartTime] +FROM ( + SELECT TOP(@__p_0) [t].[Id], [t].[Description], [t].[EndTime], [t].[StartTime], [t].[Id0], [t].[Description0], [t].[EndTime0], [t].[StartTime0] + FROM ( + SELECT DISTINCT [m].[Id], [m].[Description], [m].[EndTime], [m].[StartTime], [m0].[Id] AS [Id0], [m0].[Description] AS [Description0], [m0].[EndTime] AS [EndTime0], [m0].[StartTime] AS [StartTime0] + FROM [MainEntityDifferentTable] FOR SYSTEM_TIME AS OF '2000-01-01T00:00:00.0000000' AS [m] + INNER JOIN [MainEntityDifferentTable] AS [m0] ON [m].[Id] = [m0].[Id] + ) AS [t] + ORDER BY [t].[Id] DESC +) AS [t0] +INNER JOIN [MainEntityDifferentTable] AS [m1] ON [t0].[Id] = [m1].[Id] +LEFT JOIN [OwnedEntityDifferentTable] FOR SYSTEM_TIME AS OF '2000-01-01T00:00:00.0000000' AS [o] ON [t0].[Id] = [o].[MainEntityDifferentTableId] +LEFT JOIN [OwnedEntityDifferentTable] AS [o0] ON [t0].[Id0] = [o0].[MainEntityDifferentTableId] +LEFT JOIN [OwnedEntityDifferentTable] AS [o1] ON [m1].[Id] = [o1].[MainEntityDifferentTableId] +ORDER BY [t0].[Id] DESC"); + } + + [ConditionalTheory] + [InlineData(true)] + [InlineData(false)] + public virtual async Task Temporal_owned_complex_with_nontrivial_alias(bool async) + { + var contextFactory = await InitializeAsync(); + using (var context = contextFactory.CreateContext()) + { + var date = new DateTime(2000, 1, 1); + + var query = context.MainEntitiesDifferentTable + .Join(context.MainEntitiesDifferentTable.TemporalAsOf(date), x => x.Id, x => x.Id, (o, i) => new { o, i }) + .Distinct().OrderByDescending(x => x.o.Id).Take(3) + .Join(context.MainEntitiesDifferentTable, xx => xx.o.Id, x => x.Id, (o, i) => new { o, i }); + + var _ = async ? await query.ToListAsync() : query.ToList(); + } + + AssertSql( + @"@__p_0='3' + +SELECT [t0].[Id], [t0].[Description], [t0].[EndTime], [t0].[StartTime], [o].[MainEntityDifferentTableId], [o].[Description], [o].[EndTime], [o].[StartTime], [t0].[Id0], [t0].[Description0], [t0].[EndTime0], [t0].[StartTime0], [o0].[MainEntityDifferentTableId], [o0].[Description], [o0].[EndTime], [o0].[StartTime], [m1].[Id], [m1].[Description], [m1].[EndTime], [m1].[StartTime], [o1].[MainEntityDifferentTableId], [o1].[Description], [o1].[EndTime], [o1].[StartTime] +FROM ( + SELECT TOP(@__p_0) [t].[Id], [t].[Description], [t].[EndTime], [t].[StartTime], [t].[Id0], [t].[Description0], [t].[EndTime0], [t].[StartTime0] + FROM ( + SELECT DISTINCT [m].[Id], [m].[Description], [m].[EndTime], [m].[StartTime], [m0].[Id] AS [Id0], [m0].[Description] AS [Description0], [m0].[EndTime] AS [EndTime0], [m0].[StartTime] AS [StartTime0] + FROM [MainEntityDifferentTable] AS [m] + INNER JOIN [MainEntityDifferentTable] FOR SYSTEM_TIME AS OF '2000-01-01T00:00:00.0000000' AS [m0] ON [m].[Id] = [m0].[Id] + ) AS [t] + ORDER BY [t].[Id] DESC +) AS [t0] +INNER JOIN [MainEntityDifferentTable] AS [m1] ON [t0].[Id] = [m1].[Id] +LEFT JOIN [OwnedEntityDifferentTable] AS [o] ON [t0].[Id] = [o].[MainEntityDifferentTableId] +LEFT JOIN [OwnedEntityDifferentTable] FOR SYSTEM_TIME AS OF '2000-01-01T00:00:00.0000000' AS [o0] ON [t0].[Id0] = [o0].[MainEntityDifferentTableId] +LEFT JOIN [OwnedEntityDifferentTable] AS [o1] ON [m1].[Id] = [o1].[MainEntityDifferentTableId] +ORDER BY [t0].[Id] DESC"); + } + + [ConditionalTheory] + [InlineData(true)] + [InlineData(false)] + public virtual async Task Temporal_owned_range_operation_negative(bool async) + { + var contextFactory = await InitializeAsync(); + using (var context = contextFactory.CreateContext()) + { + var message = async + ? (await Assert.ThrowsAsync( + () => context.MainEntitiesDifferentTable.TemporalAll().ToListAsync())).Message + : Assert.Throws(() => context.MainEntitiesDifferentTable.TemporalAll().ToList()).Message; + + Assert.Equal( + SqlServerStrings.TemporalNavigationExpansionOnlySupportedForAsOf("AsOf"), + //SqlServerStrings.TemporalOwnedTypeMappedToDifferentTableOnlySupportedForAsOf("AsOf"), + message); + } + } + + [ConditionalTheory] + [InlineData(true)] + [InlineData(false)] + public virtual async Task Temporal_owned_mapped_to_same_table(bool async) + { + var contextFactory = await InitializeAsync(); + using (var context = contextFactory.CreateContext()) + { + var date = new DateTime(2000, 1, 1); + var query = context.MainEntitiesSameTable.TemporalAsOf(date); + + var _ = async ? await query.ToListAsync() : query.ToList(); + } + + AssertSql( + @"SELECT [m].[Id], [m].[EndTime], [m].[Name], [m].[StartTime], [m].[EndTime], [m].[OwnedEntity_Name], [m].[OwnedEntity_Number], [m].[StartTime], [m].[OwnedEntity_Nested_Name], [m].[OwnedEntity_Nested_Number] +FROM [MainEntitiesSameTable] FOR SYSTEM_TIME AS OF '2000-01-01T00:00:00.0000000' AS [m]"); + } + + [ConditionalTheory] + [InlineData(true)] + [InlineData(false)] + public virtual async Task Temporal_owned_many(bool async) + { + var contextFactory = await InitializeAsync(); + using (var context = contextFactory.CreateContext()) + { + var date = new DateTime(2000, 1, 1); + var query = context.MainEntitiesMany.TemporalAsOf(date); + + var _ = async ? await query.ToListAsync() : query.ToList(); + } + + AssertSql( + @"SELECT [m].[Id], [m].[Name], [m].[PeriodEnd], [m].[PeriodStart], [o].[MainEntityManyId], [o].[Id], [o].[Name], [o].[PeriodEnd], [o].[PeriodStart] +FROM [MainEntitiesMany] FOR SYSTEM_TIME AS OF '2000-01-01T00:00:00.0000000' AS [m] +LEFT JOIN [OwnedEntityMany] FOR SYSTEM_TIME AS OF '2000-01-01T00:00:00.0000000' AS [o] ON [m].[Id] = [o].[MainEntityManyId] +ORDER BY [m].[Id], [o].[MainEntityManyId]"); + } + + public class MainEntityDifferentTable + { + public int Id { get; set; } + public string Description { get; set; } + public OwnedEntityDifferentTable OwnedEntity { get; set; } + } + + public class OwnedEntityDifferentTable + { + public string Description { get; set; } + } + + public class MainEntitySameTable + { + public int Id { get; set; } + public string Name { get; set; } + + public OwnedEntitySameTable OwnedEntity { get; set; } + } + + public class OwnedEntitySameTable + { + public string Name { get; set; } + public int Number { get; set; } + + public OwnedEntitySameTableNested Nested { get; set; } + } + + public class OwnedEntitySameTableNested + { + public string Name { get; set; } + public int Number { get; set; } + } + + public class MainEntityMany + { + public int Id { get; set; } + public string Name { get; set; } + public List OwnedCollection { get; set; } + } + + public class OwnedEntityMany + { + public string Name { get; set; } + } + + public class MyContext26451 : DbContext + { + public MyContext26451(DbContextOptions options) + : base(options) + { + } + + public DbSet MainEntitiesDifferentTable { get; set; } + public DbSet MainEntitiesSameTable { get; set; } + public DbSet MainEntitiesMany { get; set; } + + protected override void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity().ToTable("MainEntityDifferentTable", tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("StartTime"); + ttb.HasPeriodEnd("EndTime"); + ttb.UseHistoryTable("ConfHistory"); + })); + modelBuilder.Entity().Property(me => me.Id).UseIdentityColumn(); + modelBuilder.Entity().OwnsOne(me => me.OwnedEntity).WithOwner(); + modelBuilder.Entity().OwnsOne(me => me.OwnedEntity, oe => + { + oe.ToTable("OwnedEntityDifferentTable", tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("StartTime"); + ttb.HasPeriodEnd("EndTime"); + ttb.UseHistoryTable("OwnedEntityHistory"); + })); + }); + + modelBuilder.Entity(eb => + { + eb.ToTable(tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("StartTime").HasColumnName("StartTime"); + ttb.HasPeriodEnd("EndTime").HasColumnName("EndTime"); + })); + + eb.OwnsOne(x => x.OwnedEntity, oeb => + { + oeb.WithOwner(); + oeb.ToTable(tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("StartTime").HasColumnName("StartTime"); + ttb.HasPeriodEnd("EndTime").HasColumnName("EndTime"); + })); + oeb.OwnsOne(x => x.Nested, neb => + { + neb.WithOwner(); + neb.ToTable(tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("StartTime").HasColumnName("StartTime"); + ttb.HasPeriodEnd("EndTime").HasColumnName("EndTime"); + })); + }); + }); + }); + + modelBuilder.Entity(eb => + { + eb.ToTable(tb => tb.IsTemporal()); + eb.OwnsMany(x => x.OwnedCollection, oeb => oeb.ToTable(tb => tb.IsTemporal())); + }); + } + } + + [ConditionalTheory] + [InlineData(true)] + [InlineData(false)] + public virtual async Task Temporal_can_query_shared_derived_hierarchy(bool async) + { + var contectFactory = await InitializeAsync(OnModelCreating); + using var context = contectFactory.CreateContext(); + var query = context.Set().TemporalAsOf(new DateTime(2000, 1, 1)); + var _ = async ? await query.ToListAsync() : query.ToList(); + + AssertSql( + @"SELECT [v].[Name], [v].[Capacity], [v].[FuelTank_Discriminator], [v].[End], [v].[FuelType], [v].[Start], [v].[GrainGeometry] +FROM [Vehicles] FOR SYSTEM_TIME AS OF '2000-01-01T00:00:00.0000000' AS [v] +INNER JOIN ( + SELECT [v0].[Name], [v0].[Discriminator], [v0].[End], [v0].[SeatingCapacity], [v0].[Start], [v0].[AttachedVehicleName] + FROM [Vehicles] FOR SYSTEM_TIME AS OF '2000-01-01T00:00:00.0000000' AS [v0] + WHERE [v0].[Discriminator] IN (N'PoweredVehicle', N'CompositeVehicle') +) AS [t] ON [v].[Name] = [t].[Name] +WHERE [v].[Capacity] IS NOT NULL AND [v].[FuelTank_Discriminator] IS NOT NULL +UNION +SELECT [v1].[Name], [v1].[Capacity], [v1].[FuelTank_Discriminator], [v1].[End], [v1].[FuelType], [v1].[Start], [v1].[GrainGeometry] +FROM [Vehicles] FOR SYSTEM_TIME AS OF '2000-01-01T00:00:00.0000000' AS [v1] +INNER JOIN ( + SELECT [v2].[Name], [v2].[Computed], [v2].[Description], [v2].[Engine_Discriminator], [v2].[End], [v2].[Start], [t2].[Name] AS [Name0] + FROM [Vehicles] FOR SYSTEM_TIME AS OF '2000-01-01T00:00:00.0000000' AS [v2] + INNER JOIN ( + SELECT [v3].[Name], [v3].[Discriminator], [v3].[End], [v3].[SeatingCapacity], [v3].[Start], [v3].[AttachedVehicleName] + FROM [Vehicles] FOR SYSTEM_TIME AS OF '2000-01-01T00:00:00.0000000' AS [v3] + WHERE [v3].[Discriminator] IN (N'PoweredVehicle', N'CompositeVehicle') + ) AS [t2] ON [v2].[Name] = [t2].[Name] + WHERE [v2].[Engine_Discriminator] IN (N'ContinuousCombustionEngine', N'IntermittentCombustionEngine', N'SolidRocket') +) AS [t1] ON [v1].[Name] = [t1].[Name] +WHERE [v1].[Capacity] IS NOT NULL AND [v1].[FuelTank_Discriminator] IS NOT NULL"); + } + + protected Task> InitializeAsync( + Action onModelCreating, bool seed = true) + { + return InitializeAsync( + onModelCreating, shouldLogCategory: _ => true, seed: seed ? c => c.Seed() : null); + } + + protected virtual void OnModelCreating(ModelBuilder modelBuilder) + { + modelBuilder.Entity( + eb => + { + eb.ToTable(tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("Start").HasColumnName("Start"); + ttb.HasPeriodEnd("End").HasColumnName("End"); + })); + eb.HasDiscriminator("Discriminator"); + eb.Property("Discriminator").HasColumnName("Discriminator"); + eb.ToTable("Vehicles"); + }); + + modelBuilder.Entity(); + + modelBuilder.Entity() + .ToTable("Vehicles", tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("Start").HasColumnName("Start"); + ttb.HasPeriodEnd("End").HasColumnName("End"); + })); + + modelBuilder.Entity().ToTable("Vehicles", tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("Start").HasColumnName("Start"); + ttb.HasPeriodEnd("End").HasColumnName("End"); + })); + + modelBuilder.Entity().ToTable("Vehicles", tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("Start").HasColumnName("Start"); + ttb.HasPeriodEnd("End").HasColumnName("End"); + })); + + modelBuilder.Entity().ToTable("Vehicles", tb => tb.IsTemporal(ttb => + { + ttb.HasPeriodStart("Start").HasColumnName("Start"); + ttb.HasPeriodEnd("End").HasColumnName("End"); + })); + } +} diff --git a/test/EFCore.SqlServer.Tests/Infrastructure/SqlServerModelValidatorTest.cs b/test/EFCore.SqlServer.Tests/Infrastructure/SqlServerModelValidatorTest.cs index d5dc90ebda7..075a4693697 100644 --- a/test/EFCore.SqlServer.Tests/Infrastructure/SqlServerModelValidatorTest.cs +++ b/test/EFCore.SqlServer.Tests/Infrastructure/SqlServerModelValidatorTest.cs @@ -781,14 +781,25 @@ public void Temporal_doesnt_work_on_TPH() } [ConditionalFact] - public void Temporal_doesnt_work_on_table_splitting() + public void Temporal_doesnt_work_on_table_splitting_with_inconsistent_period_mappings() { var modelBuilder = CreateConventionalModelBuilder(); modelBuilder.Entity().ToTable("Splitting", tb => tb.IsTemporal()); modelBuilder.Entity().ToTable("Splitting", tb => tb.IsTemporal()); modelBuilder.Entity().HasOne(x => x.Details).WithOne().HasForeignKey(x => x.Id); - VerifyError(SqlServerStrings.TemporalNotSupportedForTableSplitting("Splitting"), modelBuilder); + VerifyError(SqlServerStrings.TemporalNotSupportedForTableSplittingWithInconsistentPeriodMapping("start", "Splitting2", "PeriodStart", "Splitting2_PeriodStart", "PeriodStart"), modelBuilder); + } + + [ConditionalFact] + public void Temporal_doesnt_work_on_table_splitting_when_some_types_are_temporal_and_some_are_not() + { + var modelBuilder = CreateConventionalModelBuilder(); + modelBuilder.Entity().ToTable("Splitting"); + modelBuilder.Entity().ToTable("Splitting", tb => tb.IsTemporal()); + modelBuilder.Entity().HasOne(x => x.Details).WithOne().HasForeignKey(x => x.Id); + + VerifyError(SqlServerStrings.TemporalAllEntitiesMappedToSameTableMustBeTemporal("Splitting1"), modelBuilder); } public class Human