diff --git a/src/EFCore.Relational/Query/EntityProjectionExpression.cs b/src/EFCore.Relational/Query/EntityProjectionExpression.cs index cf957cd0a0d..4b79866c207 100644 --- a/src/EFCore.Relational/Query/EntityProjectionExpression.cs +++ b/src/EFCore.Relational/Query/EntityProjectionExpression.cs @@ -23,49 +23,37 @@ namespace Microsoft.EntityFrameworkCore.Query /// public class EntityProjectionExpression : Expression { - private readonly IDictionary _propertyExpressionsCache - = new Dictionary(); - - private readonly IDictionary _navigationExpressionsCache + private readonly IDictionary _propertyExpressions = new Dictionary(); + private readonly IDictionary _navigationExpressions = new Dictionary(); - private readonly TableExpressionBase _innerTable; - private readonly bool _nullable; - - /// - /// Creates a new instance of the class. - /// - /// The entity type to shape. - /// The table from which entity columns are being projected out. - /// A bool value indicating whether this entity instance can be null. - public EntityProjectionExpression([NotNull] IEntityType entityType, [NotNull] TableExpressionBase innerTable, bool nullable) - { - Check.NotNull(entityType, nameof(entityType)); - Check.NotNull(innerTable, nameof(innerTable)); - - EntityType = entityType; - _innerTable = innerTable; - _nullable = nullable; - } - /// /// Creates a new instance of the class. /// /// The entity type to shape. /// A dictionary of column expressions corresponding to properties of the entity type. - public EntityProjectionExpression([NotNull] IEntityType entityType, [NotNull] IDictionary propertyExpressions) + /// A dictionary of to discriminator each entity type in hierarchy. + public EntityProjectionExpression( + [NotNull] IEntityType entityType, + [NotNull] IDictionary propertyExpressions, + [CanBeNull] IReadOnlyDictionary discriminatorExpressions = null) { Check.NotNull(entityType, nameof(entityType)); Check.NotNull(propertyExpressions, nameof(propertyExpressions)); EntityType = entityType; - _propertyExpressionsCache = propertyExpressions; + _propertyExpressions = propertyExpressions; + DiscriminatorExpressions = discriminatorExpressions; } /// /// The entity type being projected out. /// public virtual IEntityType EntityType { get; } + /// + /// Dictionary of discriminator expressions. + /// + public virtual IReadOnlyDictionary DiscriminatorExpressions { get; } /// public sealed override ExpressionType NodeType => ExpressionType.Extension; /// @@ -76,18 +64,9 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) { Check.NotNull(visitor, nameof(visitor)); - if (_innerTable != null) - { - var table = (TableExpressionBase)visitor.Visit(_innerTable); - - return table != _innerTable - ? new EntityProjectionExpression(EntityType, table, _nullable) - : this; - } - var changed = false; var newCache = new Dictionary(); - foreach (var expression in _propertyExpressionsCache) + foreach (var expression in _propertyExpressions) { var newExpression = (ColumnExpression)visitor.Visit(expression.Value); changed |= newExpression != expression.Value; @@ -95,8 +74,21 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) newCache[expression.Key] = newExpression; } + Dictionary newDiscriminators = null; + if (DiscriminatorExpressions != null) + { + newDiscriminators = new Dictionary(); + foreach (var expression in DiscriminatorExpressions) + { + var newExpression = (SqlExpression)visitor.Visit(expression.Value); + changed |= newExpression != expression.Value; + + newDiscriminators[expression.Key] = newExpression; + } + } + return changed - ? new EntityProjectionExpression(EntityType, newCache) + ? new EntityProjectionExpression(EntityType, newCache, newDiscriminators) : this; } @@ -106,18 +98,13 @@ protected override Expression VisitChildren(ExpressionVisitor visitor) /// A new entity projection expression which can project nullable entity. public virtual EntityProjectionExpression MakeNullable() { - if (_innerTable != null) - { - return new EntityProjectionExpression(EntityType, _innerTable, nullable: true); - } - var newCache = new Dictionary(); - foreach (var expression in _propertyExpressionsCache) + foreach (var expression in _propertyExpressions) { newCache[expression.Key] = expression.Value.MakeNullable(); } - return new EntityProjectionExpression(EntityType, newCache); + return new EntityProjectionExpression(EntityType, newCache, DiscriminatorExpressions); } /// @@ -129,13 +116,8 @@ public virtual EntityProjectionExpression UpdateEntityType([NotNull] IEntityType { Check.NotNull(derivedType, nameof(derivedType)); - if (_innerTable != null) - { - return new EntityProjectionExpression(derivedType, _innerTable, _nullable); - } - var propertyExpressionCache = new Dictionary(); - foreach (var kvp in _propertyExpressionsCache) + foreach (var kvp in _propertyExpressions) { var property = kvp.Key; if (derivedType.IsAssignableFrom(property.DeclaringEntityType) @@ -145,7 +127,22 @@ public virtual EntityProjectionExpression UpdateEntityType([NotNull] IEntityType } } - return new EntityProjectionExpression(derivedType, propertyExpressionCache); + Dictionary discriminatorExpressions = null; + if (DiscriminatorExpressions != null) + { + discriminatorExpressions = new Dictionary(); + foreach (var kvp in DiscriminatorExpressions) + { + var entityType = kvp.Key; + if (derivedType.IsAssignableFrom(entityType) + || entityType.IsAssignableFrom(derivedType)) + { + discriminatorExpressions[entityType] = kvp.Value; + } + } + } + + return new EntityProjectionExpression(derivedType, propertyExpressionCache, discriminatorExpressions); } /// @@ -168,13 +165,7 @@ public virtual ColumnExpression BindProperty([NotNull] IProperty property) property.Name)); } - if (!_propertyExpressionsCache.TryGetValue(property, out var expression)) - { - expression = new ColumnExpression(property, _innerTable, _nullable); - _propertyExpressionsCache[property] = expression; - } - - return expression; + return _propertyExpressions[property]; } /// @@ -198,7 +189,7 @@ public virtual void AddNavigationBinding([NotNull] INavigation navigation, [NotN navigation.Name)); } - _navigationExpressionsCache[navigation] = entityShaper; + _navigationExpressions[navigation] = entityShaper; } /// @@ -222,7 +213,7 @@ public virtual EntityShaperExpression BindNavigation([NotNull] INavigation navig navigation.Name)); } - return _navigationExpressionsCache.TryGetValue(navigation, out var expression) + return _navigationExpressions.TryGetValue(navigation, out var expression) ? expression : null; } diff --git a/src/EFCore.Relational/Query/RelationalEntityShaperExpression.cs b/src/EFCore.Relational/Query/RelationalEntityShaperExpression.cs index 974a67e2b13..baddbf30cad 100644 --- a/src/EFCore.Relational/Query/RelationalEntityShaperExpression.cs +++ b/src/EFCore.Relational/Query/RelationalEntityShaperExpression.cs @@ -4,10 +4,12 @@ using System; using System.Linq; using System.Linq.Expressions; +using System.Reflection; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Metadata.Internal; +using Microsoft.EntityFrameworkCore.Storage; using Microsoft.EntityFrameworkCore.Utilities; namespace Microsoft.EntityFrameworkCore.Query @@ -23,6 +25,14 @@ namespace Microsoft.EntityFrameworkCore.Query /// public class RelationalEntityShaperExpression : EntityShaperExpression { + private static readonly MethodInfo _createUnableToIdentifyConcreteTypeException + = typeof(RelationalEntityShaperExpression).GetTypeInfo() + .GetDeclaredMethod(nameof(CreateUnableToIdentifyConcreteTypeException)); + + [UsedImplicitly] + private static Exception CreateUnableToIdentifyConcreteTypeException() + => new InvalidOperationException(""); + /// /// Creates a new instance of the class. /// @@ -55,11 +65,34 @@ protected override LambdaExpression GenerateMaterializationCondition(IEntityType { Check.NotNull(entityType, nameof(EntityType)); - var baseCondition = base.GenerateMaterializationCondition(entityType, nullable); + LambdaExpression baseCondition; + if (entityType.GetDiscriminatorProperty() == null + && entityType.GetDirectlyDerivedTypes().Any()) + { + // TPT + var valueBufferParameter = Parameter(typeof(ValueBuffer)); + var body = entityType.IsAbstract() + ? Block(Throw(Call(_createUnableToIdentifyConcreteTypeException)), Constant(null, typeof(IEntityType))) + : (Expression)Constant(entityType, typeof(IEntityType)); // Default type + var concreteEntityTypes = entityType.GetDerivedTypes().Where(dt => !dt.IsAbstract()).ToArray(); + for (var i = 0; i < concreteEntityTypes.Length; i++) + { + body = Condition( + valueBufferParameter.CreateValueBufferReadValueExpression(typeof(bool), i, property: null), + Constant(concreteEntityTypes[i], typeof(IEntityType)), + body); + } + + baseCondition = Lambda(body, valueBufferParameter); + } + else + { + baseCondition = base.GenerateMaterializationCondition(entityType, nullable); + } if (entityType.FindPrimaryKey() != null) { - var linkingFks = entityType.GetViewOrTableMappings().SingleOrDefault()?.Table.GetRowInternalForeignKeys(entityType); + var linkingFks = entityType.GetViewOrTableMappings().FirstOrDefault()?.Table.GetRowInternalForeignKeys(entityType); if (linkingFks != null && linkingFks.Any()) { diff --git a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs index 2d3e4fdb789..71ff3926f88 100644 --- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs @@ -744,16 +744,49 @@ protected override ShapedQueryExpression TranslateOfType(ShapedQueryExpression s var derivedType = entityType.GetDerivedTypes().SingleOrDefault(et => et.ClrType == resultType); if (derivedType != null) { - if (!derivedType.GetRootType().GetIsDiscriminatorMappingComplete() - || !derivedType.GetAllBaseTypesInclusiveAscending() - .All(e => (e == derivedType || e.IsAbstract()) && !HasSiblings(e))) + var discriminatorProperty = entityType.GetDiscriminatorProperty(); + if (discriminatorProperty == null) { var selectExpression = (SelectExpression)source.QueryExpression; var concreteEntityTypes = derivedType.GetConcreteDerivedTypesInclusive().ToList(); var projectionBindingExpression = (ProjectionBindingExpression)entityShaperExpression.ValueBufferExpression; + + var projectionMember = projectionBindingExpression.ProjectionMember; + Check.DebugAssert( + new ProjectionMember().Equals(projectionMember), + "Invalid ProjectionMember when processing OfType"); + + var entityProjectionExpression = (EntityProjectionExpression)selectExpression.GetMappedProjection( + projectionBindingExpression.ProjectionMember); + + var predicate = entityProjectionExpression.DiscriminatorExpressions + .Where(kvp => concreteEntityTypes.Contains(kvp.Key)) + .Select(kvp => kvp.Value) + .Aggregate((l, r) => _sqlExpressionFactory.OrElse(l, r)); + + selectExpression.ApplyPredicate(predicate); + selectExpression.ReplaceProjectionMapping( + new Dictionary + { + { projectionMember, entityProjectionExpression.UpdateEntityType(derivedType) } + }); + } + else if (!derivedType.GetRootType().GetIsDiscriminatorMappingComplete() + || !derivedType.GetAllBaseTypesInclusiveAscending() + .All(e => (e == derivedType || e.IsAbstract()) && !HasSiblings(e))) + { + var selectExpression = (SelectExpression)source.QueryExpression; + var concreteEntityTypes = derivedType.GetConcreteDerivedTypesInclusive().ToList(); + var projectionBindingExpression = (ProjectionBindingExpression)entityShaperExpression.ValueBufferExpression; + + var projectionMember = projectionBindingExpression.ProjectionMember; + Check.DebugAssert( + new ProjectionMember().Equals(projectionMember), + "Invalid ProjectionMember when processing OfType"); + var entityProjectionExpression = (EntityProjectionExpression)selectExpression.GetMappedProjection( projectionBindingExpression.ProjectionMember); - var discriminatorColumn = entityProjectionExpression.BindProperty(entityType.GetDiscriminatorProperty()); + var discriminatorColumn = entityProjectionExpression.BindProperty(discriminatorProperty); var predicate = concreteEntityTypes.Count == 1 ? _sqlExpressionFactory.Equal( @@ -765,19 +798,10 @@ protected override ShapedQueryExpression TranslateOfType(ShapedQueryExpression s negated: false); selectExpression.ApplyPredicate(predicate); - - var projectionMember = projectionBindingExpression.ProjectionMember; - - Check.DebugAssert( - new ProjectionMember().Equals(projectionMember), - "Invalid ProjectionMember when processing OfType"); - - var entityProjection = (EntityProjectionExpression)selectExpression.GetMappedProjection(projectionMember); - selectExpression.ReplaceProjectionMapping( new Dictionary { - { projectionMember, entityProjection.UpdateEntityType(derivedType) } + { projectionMember, entityProjectionExpression.UpdateEntityType(derivedType) } }); } @@ -1285,16 +1309,31 @@ private Expression TryExpand(Expression source, MemberIdentity member) var innerShaper = entityProjectionExpression.BindNavigation(navigation); if (innerShaper == null) { - if (entityType.GetViewOrTableMappings().Single().Table - .GetReferencingRowInternalForeignKeys(foreignKey.PrincipalEntityType)?.Contains(foreignKey) == true) + // If navigation is defined on derived type and entity type is part of TPT then we need to get ITableBase for derived type. + var table = navigation.DeclaringEntityType.BaseType == null + || entityType.GetDiscriminatorProperty() != null + ? navigation.DeclaringEntityType.GetViewOrTableMappings().Single().Table + : navigation.DeclaringEntityType.GetViewOrTableMappings().Select(tm => tm.Table) + .Except(navigation.DeclaringEntityType.BaseType.GetViewOrTableMappings().Select(tm => tm.Table)) + .Single(); + if (table.GetReferencingRowInternalForeignKeys(foreignKey.PrincipalEntityType)?.Contains(foreignKey) == true) { - // Since we are not going to update table or visit, we always generate propertyExpressions - // We just first column of PK to figure out the base table + // TODO: Update this code to deal with TPT on dependent end + // Mapped to same table + // We get identifying column to figure out tableExpression and nullability of most principal table var identifyingColumn = entityProjectionExpression.BindProperty(entityType.FindPrimaryKey().Properties.First()); + // Either principal side is nullable already + // Or navigation is on derived type and principal is TPT then navigation would project nullable PK columns. + // Derived owned navigation does not de-dupe the PK column which for principal is from base table and for dependent on derived table + var principalNullable = identifyingColumn.IsNullable + || (entityType.GetDiscriminatorProperty() == null + && navigation.DeclaringEntityType.IsStrictlyDerivedFrom(entityShaperExpression.EntityType)); + var propertyExpressions = identifyingColumn.Table is TableExpression innerTable - ? GetPropertyExpressionsFromTable(targetEntityType, innerTable, identifyingColumn.IsNullable) - // Pull columns out of inner subquery - : GetPropertyExpressionsFromSubquery(targetEntityType, identifyingColumn, identifyingColumn.IsNullable); + ? GetPropertyExpressionsFromTable( + targetEntityType, table, _selectExpression, innerTable, principalNullable) + // If the principal table is SelectExpression then we may need to populate inner projection + : GetPropertyExpressionsFromSubquery(targetEntityType, table, identifyingColumn, principalNullable); innerShaper = new RelationalEntityShaperExpression( targetEntityType, new EntityProjectionExpression(targetEntityType, propertyExpressions), true); @@ -1323,10 +1362,11 @@ private Expression TryExpand(Expression source, MemberIdentity member) var joinPredicate = _sqlTranslator.Translate(Expression.Equal(outerKey, innerKey)); _selectExpression.AddLeftJoin(innerSelectExpression, joinPredicate); var leftJoinTable = ((LeftJoinExpression)_selectExpression.Tables.Last()).Table; + // TODO: Update this code to pull discriminator expressions from joined table when dependent is TPT + var propertyExpressions = GetPropertyExpressionsFromJoinedTable(targetEntityType, table, leftJoinTable); + innerShaper = new RelationalEntityShaperExpression( - targetEntityType, - new EntityProjectionExpression(targetEntityType, leftJoinTable, true), - true); + targetEntityType, new EntityProjectionExpression(targetEntityType, propertyExpressions), true); } entityProjectionExpression.AddNavigationBinding(navigation, innerShaper); @@ -1335,13 +1375,19 @@ private Expression TryExpand(Expression source, MemberIdentity member) return innerShaper; } + private static IDictionary GetPropertyExpressionsFromSubquery( + IEntityType entityType, ITableBase table, ColumnExpression identifyingColumn, bool nullable) + { + var subquery = (SelectExpression)identifyingColumn.Table; + var subqueryIdentifyingColumn = (ColumnExpression)subquery.Projection + .SingleOrDefault(e => string.Equals(e.Alias, identifyingColumn.Name, StringComparison.OrdinalIgnoreCase)).Expression; + var subqueryPropertyExpressions = subqueryIdentifyingColumn.Table is TableExpression innerTable + ? GetPropertyExpressionsFromTable(entityType, table, subquery, innerTable, nullable) + : GetPropertyExpressionsFromSubquery(entityType, table, subqueryIdentifyingColumn, nullable); - private static IDictionary LiftPropertyExpressionsFromSubquery( - IDictionary propertyExpressions, SelectExpression subquery) - { var newPropertyExpressions = new Dictionary(); - foreach (var item in propertyExpressions) + foreach (var item in subqueryPropertyExpressions) { newPropertyExpressions[item.Key] = new ColumnExpression( subquery.Projection[subquery.AddToProjection(item.Value)], subquery); @@ -1350,28 +1396,49 @@ private static IDictionary LiftPropertyExpressionsF return newPropertyExpressions; } - private static IDictionary GetPropertyExpressionsFromSubquery( - IEntityType entityType, ColumnExpression identifyingColumn, bool nullable) + private static IDictionary GetPropertyExpressionsFromTable( + IEntityType entityType, ITableBase table, SelectExpression selectExpression, TableExpression tableExpression, bool nullable) { - var subquery = (SelectExpression)identifyingColumn.Table; - var subqueryIdentifyingColumn = (ColumnExpression)subquery.Projection - .SingleOrDefault(e => string.Equals(e.Alias, identifyingColumn.Name, StringComparison.OrdinalIgnoreCase)).Expression; + if (!string.Equals(tableExpression.Name, table.Name, StringComparison.OrdinalIgnoreCase)) + { + // Fetch the table for the type which is defininig the navigation since dependent would be in that table + tableExpression = selectExpression.Tables + .Select(t => (t as InnerJoinExpression)?.Table ?? (t as LeftJoinExpression)?.Table ?? t) + .Cast() + .First(t => string.Equals(t.Name, table.Name, StringComparison.OrdinalIgnoreCase)); + } - var subqueryPropertyExpressions = subqueryIdentifyingColumn.Table is TableExpression innerTable - ? GetPropertyExpressionsFromTable(entityType, innerTable, nullable) - : GetPropertyExpressionsFromSubquery(entityType, subqueryIdentifyingColumn, nullable); + var propertyExpressions = new Dictionary(); + foreach (var property in entityType + .GetAllBaseTypes().Concat(entityType.GetDerivedTypesInclusive()).SelectMany(EntityTypeExtensions.GetDeclaredProperties)) + { + var column = table is ITable + ? (IColumnBase)property.GetTableColumnMappings().Where(cm => cm.TableMapping.Table == table + && cm.TableMapping.EntityType == property.DeclaringEntityType).Single().Column + : property.GetViewColumnMappings().Where(cm => cm.TableMapping.Table == table + && cm.TableMapping.EntityType == property.DeclaringEntityType).Single().Column; + + propertyExpressions[property] = new ColumnExpression( + property, column, tableExpression, nullable || !property.IsPrimaryKey()); + } - return LiftPropertyExpressionsFromSubquery(subqueryPropertyExpressions, subquery); + return propertyExpressions; } - private static IDictionary GetPropertyExpressionsFromTable( - IEntityType entityType, TableExpression table, bool nullable) + private static IDictionary GetPropertyExpressionsFromJoinedTable( + IEntityType entityType, ITableBase table, TableExpressionBase tableExpression) { var propertyExpressions = new Dictionary(); foreach (var property in entityType .GetAllBaseTypes().Concat(entityType.GetDerivedTypesInclusive()).SelectMany(EntityTypeExtensions.GetDeclaredProperties)) { - propertyExpressions[property] = new ColumnExpression(property, table, nullable || !property.IsPrimaryKey()); + var column = table is ITable + ? (IColumnBase)property.GetTableColumnMappings().Where(cm => cm.TableMapping.Table == table + && cm.TableMapping.EntityType == property.DeclaringEntityType).Single().Column + : property.GetViewColumnMappings().Where(cm => cm.TableMapping.Table == table + && cm.TableMapping.EntityType == property.DeclaringEntityType).Single().Column; + + propertyExpressions[property] = new ColumnExpression(property, column, tableExpression, nullable: true); } return propertyExpressions; diff --git a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs index 00921b816cd..6bd29ce265e 100644 --- a/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs @@ -106,6 +106,8 @@ private static readonly MethodInfo _collectionAccessorAddMethodInfo // States to convert code to data reader read private readonly IDictionary> _materializationContextBindings = new Dictionary>(); + private readonly IDictionary _discriminatorExpressionsOffset + = new Dictionary(); public ShaperProcessingExpressionVisitor( RelationalShapedQueryCompilingExpressionVisitor parentVisitor, @@ -343,8 +345,9 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) var newExpression = (NewExpression)binaryExpression.Right; var projectionBindingExpression = (ProjectionBindingExpression)newExpression.Arguments[0]; - _materializationContextBindings[parameterExpression] - = (IDictionary)GetProjectionIndex(projectionBindingExpression); + var propertyMap = (IDictionary)GetProjectionIndex(projectionBindingExpression); + _materializationContextBindings[parameterExpression] = propertyMap; + _discriminatorExpressionsOffset[parameterExpression] = propertyMap.Values.Max() + 1; var updatedExpression = Expression.New( newExpression.Constructor, @@ -371,14 +374,15 @@ protected override Expression VisitExtension(Expression extensionExpression) switch (extensionExpression) { - case EntityShaperExpression entityShaperExpression: + case RelationalEntityShaperExpression entityShaperExpression: { var key = GenerateKey((ProjectionBindingExpression)entityShaperExpression.ValueBufferExpression); if (!_variableShaperMapping.TryGetValue(key, out var accessor)) { var entityParameter = Expression.Parameter(entityShaperExpression.Type); _variables.Add(entityParameter); - var entityMaterializationExpression = Visit(_parentVisitor.InjectEntityMaterializers(entityShaperExpression)); + var entityMaterializationExpression = _parentVisitor.InjectEntityMaterializers(entityShaperExpression); + entityMaterializationExpression = Visit(entityMaterializationExpression); _expressions.Add(Expression.Assign(entityParameter, entityMaterializationExpression)); @@ -818,19 +822,17 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp && methodCallExpression.Method.GetGenericMethodDefinition() == Infrastructure.ExpressionExtensions.ValueBufferTryReadValueMethod) { var property = (IProperty)((ConstantExpression)methodCallExpression.Arguments[2]).Value; - var propertyProjectionMap = methodCallExpression.Arguments[0] is ProjectionBindingExpression projectionBindingExpression - ? (IDictionary)GetProjectionIndex(projectionBindingExpression) - : _materializationContextBindings[ - (ParameterExpression)((MethodCallExpression)methodCallExpression.Arguments[0]).Object]; - - var projectionIndex = propertyProjectionMap[property]; + var mappingParameter = (ParameterExpression)((MethodCallExpression)methodCallExpression.Arguments[0]).Object; + var projectionIndex = property == null + ? _discriminatorExpressionsOffset[mappingParameter] + (int)((ConstantExpression)methodCallExpression.Arguments[1]).Value + : _materializationContextBindings[mappingParameter][property]; var projection = _selectExpression.Projection[projectionIndex]; return CreateGetValueExpression( _dataReaderParameter, projectionIndex, IsNullableProjection(projection), - property.GetRelationalTypeMapping(), + projection.Expression.TypeMapping, methodCallExpression.Type, property); } diff --git a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs index 7b82675d12e..dee5e368659 100644 --- a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs @@ -747,7 +747,25 @@ protected override Expression VisitTypeBinary(TypeBinaryExpression typeBinaryExp if (derivedType != null) { var concreteEntityTypes = derivedType.GetConcreteDerivedTypesInclusive().ToList(); - var discriminatorColumn = BindProperty(entityReferenceExpression, entityType.GetDiscriminatorProperty()); + var discriminatorProperty = entityType.GetDiscriminatorProperty(); + if (discriminatorProperty == null) + { + // TPT + if (entityReferenceExpression.SubqueryEntity != null) + { + throw new NotImplementedException(); + } + + var entityProjection = (EntityProjectionExpression)Visit( + entityReferenceExpression.ParameterEntity.ValueBufferExpression); + + return entityProjection.DiscriminatorExpressions + .Where(kvp => concreteEntityTypes.Contains(kvp.Key)) + .Select(kvp => kvp.Value) + .Aggregate((l, r) => _sqlExpressionFactory.OrElse(l, r)); + } + + var discriminatorColumn = BindProperty(entityReferenceExpression, discriminatorProperty); return concreteEntityTypes.Count == 1 ? _sqlExpressionFactory.Equal( diff --git a/src/EFCore.Relational/Query/SqlExpressionFactory.cs b/src/EFCore.Relational/Query/SqlExpressionFactory.cs index 0a2aaa7875e..23adc434eaf 100644 --- a/src/EFCore.Relational/Query/SqlExpressionFactory.cs +++ b/src/EFCore.Relational/Query/SqlExpressionFactory.cs @@ -757,7 +757,7 @@ public virtual SelectExpression Select(IEntityType entityType) { Check.NotNull(entityType, nameof(entityType)); - var selectExpression = new SelectExpression(entityType); + var selectExpression = new SelectExpression(entityType, this); AddConditions(selectExpression, entityType); return selectExpression; @@ -801,7 +801,7 @@ private void AddSelfConditions(SelectExpression selectExpression, IEntityType en } // Add conditions if dependent sharing table with principal - table ??= entityType.GetViewOrTableMappings().SingleOrDefault()?.Table; + table ??= entityType.GetViewOrTableMappings().FirstOrDefault()?.Table; if (table != null && table.GetRowInternalForeignKeys(entityType).Any() && !discriminatorAdded) @@ -814,7 +814,7 @@ private void AddConditions(SelectExpression selectExpression, IEntityType entity { AddSelfConditions(selectExpression, entityType, table); // Add inner join to principal if table sharing - table ??= entityType.GetViewOrTableMappings().SingleOrDefault()?.Table; + table ??= entityType.GetViewOrTableMappings().FirstOrDefault()?.Table; if (table != null) { var linkingFks = table.GetRowInternalForeignKeys(entityType); @@ -828,7 +828,7 @@ private void AddConditions(SelectExpression selectExpression, IEntityType entity } else { - var dependentSelectExpression = new SelectExpression(entityType); + var dependentSelectExpression = new SelectExpression(entityType, this); AddSelfConditions(dependentSelectExpression, entityType, table); AddInnerJoin(dependentSelectExpression, foreignKey, table); selectExpression.ApplyUnion(dependentSelectExpression, distinct: true); @@ -843,8 +843,8 @@ private void AddInnerJoin(SelectExpression selectExpression, IForeignKey foreign var outerIsPrincipal = foreignKey.PrincipalEntityType.IsAssignableFrom(outerEntityProjection.EntityType); var innerSelect = outerIsPrincipal - ? new SelectExpression(foreignKey.DeclaringEntityType) - : new SelectExpression(foreignKey.PrincipalEntityType); + ? new SelectExpression(foreignKey.DeclaringEntityType, this) + : new SelectExpression(foreignKey.PrincipalEntityType, this); if (outerIsPrincipal) { @@ -944,7 +944,7 @@ private void AddOptionalDependentConditions( // other dependents. foreach (var referencingFk in entityType.GetReferencingForeignKeys()) { - var otherSelectExpression = new SelectExpression(entityType); + var otherSelectExpression = new SelectExpression(entityType, this); var sameTable = table.GetRowInternalForeignKeys(referencingFk.DeclaringEntityType).Any(); AddInnerJoin( diff --git a/src/EFCore.Relational/Query/SqlExpressions/ColumnExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/ColumnExpression.cs index 902ee50976e..0feada9e848 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/ColumnExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/ColumnExpression.cs @@ -24,18 +24,13 @@ namespace Microsoft.EntityFrameworkCore.Query.SqlExpressions // Class is sealed because there are no public/protected constructors. Can be unsealed if this is changed. public sealed class ColumnExpression : SqlExpression { - internal ColumnExpression(IProperty property, TableExpressionBase table, bool nullable) + internal ColumnExpression(IProperty property, IColumnBase column, TableExpressionBase table, bool nullable) : this( - property.GetTableColumnMappings().Cast().Concat(property.GetViewColumnMappings()) - .FirstOrDefault()?.Column.Name // TODO: this should take table into account - ?? property.GetColumnName(), + column?.Name ?? property.GetColumnName(), table, property.ClrType, property.GetRelationalTypeMapping(), - nullable - || (property.GetTableColumnMappings().Cast().Concat(property.GetViewColumnMappings()) - .FirstOrDefault()?.Column.IsNullable // TODO: this should take table into account - ?? property.IsColumnNullable())) + nullable || (column?.IsNullable ?? property.IsColumnNullable())) { } diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs index 3853994b059..3f62c0726b5 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs @@ -118,9 +118,145 @@ internal SelectExpression(SqlExpression projection) } } - internal SelectExpression(IEntityType entityType) - : this(entityType, new TableExpression(entityType.GetViewOrTableMappings().Single().Table)) + internal SelectExpression(IEntityType entityType, ISqlExpressionFactory sqlExpressionFactory) + : base(null) { + if (entityType.BaseType == null && !entityType.GetDirectlyDerivedTypes().Any() + || entityType.GetDiscriminatorProperty() != null) + { + // Key-less entities or TPH + var table = entityType.GetViewOrTableMappings().Single().Table; + var tableExpression = new TableExpression(table); + _tables.Add(tableExpression); + + var propertyExpressions = new Dictionary(); + foreach (var property in GetAllPropertiesInHierarchy(entityType)) + { + var column = table is ITable + ? (IColumnBase)property.GetTableColumnMappings().Where(cm => cm.TableMapping.Table == table + && cm.TableMapping.EntityType == property.DeclaringEntityType).Single().Column + : property.GetViewColumnMappings().Where(cm => cm.TableMapping.Table == table + && cm.TableMapping.EntityType == property.DeclaringEntityType).Single().Column; + + propertyExpressions[property] = new ColumnExpression(property, column, tableExpression, nullable: false); + } + + var entityProjection = new EntityProjectionExpression(entityType, propertyExpressions); + _projectionMapping[new ProjectionMember()] = entityProjection; + + if (entityType.FindPrimaryKey() != null) + { + foreach (var property in entityType.FindPrimaryKey().Properties) + { + _identifier.Add((entityProjection.BindProperty(property), property.GetKeyValueComparer())); + } + } + } + else + { + // TPT + var keyProperties = entityType.FindPrimaryKey().Properties; + List outerJoinColumns = null; + var tables = new List(); + var columns = new Dictionary(); + foreach (var baseType in entityType.GetAllBaseTypesInclusive()) + { + var table = baseType.GetViewOrTableMappings().Single(m => !tables.Contains(m.Table)).Table; + tables.Add(table); + var tableExpression = new TableExpression(table); + foreach (var property in baseType.GetDeclaredProperties()) + { + var column = table is ITable + ? (IColumnBase)property.GetTableColumnMappings().Single(cm => cm.TableMapping.Table == table + && cm.TableMapping.EntityType == baseType).Column + : property.GetViewColumnMappings().Single(cm => cm.TableMapping.Table == table + && cm.TableMapping.EntityType == baseType).Column; + + var columnExpression = new ColumnExpression(property, column, tableExpression, nullable: false); + + columns[property] = columnExpression; + } + + if (_tables.Count == 0) + { + _tables.Add(tableExpression); + outerJoinColumns = new List(); + foreach (var property in keyProperties) + { + var columnExpression = columns[property]; + outerJoinColumns.Add(columnExpression); + _identifier.Add((columnExpression, property.GetKeyValueComparer())); + } + } + else + { + var innerColumns = keyProperties.Select( + p => + { + var column = table is ITable + ? (IColumnBase)p.GetTableColumnMappings().Single(cm => cm.TableMapping.Table == table + && cm.TableMapping.EntityType == baseType).Column + : p.GetViewColumnMappings().Single(cm => cm.TableMapping.Table == table + && cm.TableMapping.EntityType == baseType).Column; + + return new ColumnExpression(p, column, tableExpression, nullable: false); + }).ToList(); + + var joinPredicate = outerJoinColumns.Zip(innerColumns, (l, r) => sqlExpressionFactory.Equal(l, r)) + .Aggregate((l, r) => sqlExpressionFactory.AndAlso(l, r)); + + var joinExpression = new InnerJoinExpression(tableExpression, joinPredicate); + _tables.Add(joinExpression); + } + } + + var discriminatorExpressions = new Dictionary(); + + foreach (var derivedType in entityType.GetDerivedTypes()) + { + var table = derivedType.GetViewOrTableMappings().Single(m => !tables.Contains(m.Table)).Table; + tables.Add(table); + var tableExpression = new TableExpression(table); + foreach (var property in derivedType.GetDeclaredProperties()) + { + var column = table is ITable + ? (IColumnBase)property.GetTableColumnMappings().Single(cm => cm.TableMapping.Table == table + && cm.TableMapping.EntityType == derivedType).Column + : property.GetViewColumnMappings().Single(cm => cm.TableMapping.Table == table + && cm.TableMapping.EntityType == derivedType).Column; + + var columnExpression = new ColumnExpression(property, column, tableExpression, nullable: true); + + columns[property] = columnExpression; + } + + var innerColumns = keyProperties.Select( + p => + { + var column = table is ITable + ? (IColumnBase)p.GetTableColumnMappings().Single(cm => cm.TableMapping.Table == table + && cm.TableMapping.EntityType == derivedType).Column + : p.GetViewColumnMappings().Single(cm => cm.TableMapping.Table == table + && cm.TableMapping.EntityType == derivedType).Column; + + return new ColumnExpression(p, column, tableExpression, nullable: true); + }).ToList(); + + if (!derivedType.IsAbstract()) + { + discriminatorExpressions[derivedType] = sqlExpressionFactory.IsNotNull(innerColumns.First()); + } + + var joinPredicate = outerJoinColumns.Zip(innerColumns, (l, r) => sqlExpressionFactory.Equal(l, r)) + .Aggregate((l, r) => sqlExpressionFactory.AndAlso(l, r)); + + var joinExpression = new LeftJoinExpression(tableExpression, joinPredicate); + _tables.Add(joinExpression); + } + + var entityProjection = new EntityProjectionExpression(entityType, columns, discriminatorExpressions); + _projectionMapping[new ProjectionMember()] = entityProjection; + } } internal SelectExpression(IEntityType entityType, TableExpressionBase tableExpression) @@ -128,7 +264,13 @@ internal SelectExpression(IEntityType entityType, TableExpressionBase tableExpre { _tables.Add(tableExpression); - var entityProjection = new EntityProjectionExpression(entityType, tableExpression, false); + var propertyExpressions = new Dictionary(); + foreach (var property in GetAllPropertiesInHierarchy(entityType)) + { + propertyExpressions[property] = new ColumnExpression(property, null, tableExpression, nullable: false); + } + + var entityProjection = new EntityProjectionExpression(entityType, propertyExpressions); _projectionMapping[new ProjectionMember()] = entityProjection; if (entityType.FindPrimaryKey() != null) @@ -176,12 +318,19 @@ public void ApplyProjection() if (keyValuePair.Value is EntityProjectionExpression entityProjection) { var map = new Dictionary(); - foreach (var property in GetAllPropertiesInHierarchy(entityProjection.EntityType)) { map[property] = AddToProjection(entityProjection.BindProperty(property)); } + if (entityProjection.DiscriminatorExpressions != null) + { + foreach (var kvp in entityProjection.DiscriminatorExpressions) + { + AddToProjection(kvp.Value, $"Is{kvp.Key.ShortName()}"); + } + } + result[keyValuePair.Key] = Constant(map); } else @@ -254,19 +403,23 @@ private int AddToProjection(SqlExpression sqlExpression, string alias) return existingIndex; } - var baseAlias = alias ?? (sqlExpression as ColumnExpression)?.Name ?? (Alias != null ? "c" : null); - var currentAlias = baseAlias ?? ""; - if (Alias != null - && baseAlias != null) + var baseAlias = !string.IsNullOrEmpty(alias) + ? alias + : (sqlExpression as ColumnExpression)?.Name ?? (Alias != null ? "c" : null); + if (Alias != null) { var counter = 0; + Check.DebugAssert(baseAlias != null, "baseAlias should be non-null since this is a subquery."); + + var currentAlias = baseAlias; while (_projection.Any(pe => string.Equals(pe.Alias, currentAlias, StringComparison.OrdinalIgnoreCase))) { currentAlias = $"{baseAlias}{counter++}"; } + baseAlias = currentAlias; } - _projection.Add(new ProjectionExpression(sqlExpression, currentAlias)); + _projection.Add(new ProjectionExpression(sqlExpression, baseAlias ?? "")); return _projection.Count - 1; } @@ -288,6 +441,14 @@ public IDictionary AddToProjection([NotNull] EntityProjectionExp dictionary[property] = AddToProjection(entityProjection.BindProperty(property)); } + if (entityProjection.DiscriminatorExpressions != null) + { + foreach (var kvp in entityProjection.DiscriminatorExpressions) + { + AddToProjection(kvp.Value, $"Is{kvp.Key.ShortName()}"); + } + } + _entityProjectionCache[entityProjection] = dictionary; } @@ -770,6 +931,7 @@ void HandleEntityMapping( select2, projection2.BindProperty(property)); } + // TODO: Update following to allow set operation between TPTs _projectionMapping[projectionMember] = new EntityProjectionExpression(projection1.EntityType, propertyExpressions); } @@ -846,13 +1008,13 @@ public IDictionary PushdownIntoSubquery() // Projections may be present if added by lifting SingleResult/Enumerable in projection through join if (_projection.Any()) { - var projections = _projection.Select(pe => pe.Expression).ToList(); + var projections = _projection.ToList(); _projection.Clear(); foreach (var projection in projections) { - var outerColumn = subquery.GenerateOuterColumn(projection); + var outerColumn = subquery.GenerateOuterColumn(projection.Expression, projection.Alias); AddToProjection(outerColumn); - projectionMap[projection] = outerColumn; + projectionMap[projection.Expression] = outerColumn; } } @@ -960,7 +1122,22 @@ EntityProjectionExpression LiftEntityProjectionFromSubquery(EntityProjectionExpr propertyExpressions[property] = outerColumn; } - var newEntityProjection = new EntityProjectionExpression(entityProjection.EntityType, propertyExpressions); + Dictionary discriminatorExpressions = null; + if (entityProjection.DiscriminatorExpressions != null) + { + discriminatorExpressions = new Dictionary(); + foreach (var discriminatorExpression in entityProjection.DiscriminatorExpressions) + { + var innerProjection = discriminatorExpression.Value; + var outerColumn = subquery.GenerateOuterColumn(innerProjection, $"Is{discriminatorExpression.Key.ShortName()}"); + projectionMap[innerProjection] = outerColumn; + discriminatorExpressions[discriminatorExpression.Key] = outerColumn; + } + } + + var newEntityProjection = new EntityProjectionExpression( + entityProjection.EntityType, propertyExpressions, discriminatorExpressions); + // Also lift nested entity projections foreach (var navigation in entityProjection.EntityType .GetAllBaseTypes().Concat(entityProjection.EntityType.GetDerivedTypesInclusive()) diff --git a/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs b/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs index ffe97d4bacc..386b256e7bc 100644 --- a/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs +++ b/src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs @@ -501,12 +501,6 @@ private Expression MaterializeEntity( entityShaperExpression.MaterializationCondition.Body))); var concreteEntityTypes = entityType.GetConcreteDerivedTypesInclusive().ToArray(); - var discriminatorProperty = entityType.GetDiscriminatorProperty(); - if (discriminatorProperty == null - && concreteEntityTypes.Length > 1) - { - concreteEntityTypes = new [] { entityType }; - } var switchCases = new SwitchCase[concreteEntityTypes.Length]; for (var i = 0; i < concreteEntityTypes.Length; i++) diff --git a/test/EFCore.Relational.Specification.Tests/Query/TPTInheritanceQueryFixture.cs b/test/EFCore.Relational.Specification.Tests/Query/TPTInheritanceQueryFixture.cs index bf1a61295d9..623aafc3a96 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/TPTInheritanceQueryFixture.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/TPTInheritanceQueryFixture.cs @@ -43,11 +43,11 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con modelBuilder.Entity().Property(e => e.SugarGrams).HasColumnName("SugarGrams"); modelBuilder.Entity().Property(e => e.CaffeineGrams).HasColumnName("CaffeineGrams"); - // Keyless entities are mapped to TPH - modelBuilder.Entity().HasNoKey().ToQuery( - () => context.Set().FromSqlRaw("SELECT * FROM Animals")); - modelBuilder.Entity().HasDiscriminator().HasValue("Kiwi"); - modelBuilder.Entity().HasDiscriminator().HasValue("Eagle"); + // Keyless entities are mapped to TPH so ignoring them + modelBuilder.Ignore(); + modelBuilder.Ignore(); + modelBuilder.Ignore(); + modelBuilder.Ignore(); } } } diff --git a/test/EFCore.Relational.Specification.Tests/Query/TPTInheritanceQueryTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/TPTInheritanceQueryTestBase.cs index 98bd092e199..d1540e5e67c 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/TPTInheritanceQueryTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/TPTInheritanceQueryTestBase.cs @@ -15,232 +15,29 @@ public TPTInheritanceQueryTestBase(TFixture fixture) { } - [ConditionalFact(Skip = "Issue#2266")] - public override void Byte_enum_value_constant_used_in_projection() - { - base.Byte_enum_value_constant_used_in_projection(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Can_filter_all_animals() - { - base.Can_filter_all_animals(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Can_include_animals() - { - base.Can_include_animals(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Can_include_prey() - { - base.Can_include_prey(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Can_insert_update_delete() - { - base.Can_insert_update_delete(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Can_query_all_animals() - { - base.Can_query_all_animals(); - } - - [ConditionalFact(Skip = "Issue#2266")] + // Keyless entities does not have TPT public override void Can_query_all_animal_views() { - base.Can_query_all_animal_views(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Can_query_all_birds() - { - base.Can_query_all_birds(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Can_query_all_plants() - { - base.Can_query_all_plants(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Can_query_all_types_when_shared_column() - { - base.Can_query_all_types_when_shared_column(); } - [ConditionalFact(Skip = "Issue#2266")] - public override void Can_query_just_kiwis() - { - base.Can_query_just_kiwis(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Can_query_just_roses() - { - base.Can_query_just_roses(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Can_query_when_shared_column() - { - base.Can_query_when_shared_column(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Can_use_backwards_is_animal() - { - base.Can_use_backwards_is_animal(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Can_use_backwards_of_type_animal() - { - base.Can_use_backwards_of_type_animal(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Can_use_is_kiwi() - { - base.Can_use_is_kiwi(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Can_use_is_kiwi_in_projection() - { - base.Can_use_is_kiwi_in_projection(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Can_use_is_kiwi_with_other_predicate() - { - base.Can_use_is_kiwi_with_other_predicate(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Can_use_of_type_animal() - { - base.Can_use_of_type_animal(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Can_use_of_type_bird() - { - base.Can_use_of_type_bird(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Can_use_of_type_bird_first() - { - base.Can_use_of_type_bird_first(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Can_use_of_type_bird_predicate() - { - base.Can_use_of_type_bird_predicate(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Can_use_of_type_bird_with_projection() - { - base.Can_use_of_type_bird_with_projection(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Can_use_of_type_kiwi() - { - base.Can_use_of_type_kiwi(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Can_use_of_type_kiwi_where_north_on_derived_property() - { - base.Can_use_of_type_kiwi_where_north_on_derived_property(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Can_use_of_type_kiwi_where_south_on_derived_property() - { - base.Can_use_of_type_kiwi_where_south_on_derived_property(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Can_use_of_type_rose() - { - base.Can_use_of_type_rose(); - } - - [ConditionalFact(Skip = "Issue#2266")] + // TPT does not have discriminator public override void Discriminator_used_when_projection_over_derived_type() { - base.Discriminator_used_when_projection_over_derived_type(); } - [ConditionalFact(Skip = "Issue#2266")] + // TPT does not have discriminator public override void Discriminator_used_when_projection_over_derived_type2() { - base.Discriminator_used_when_projection_over_derived_type2(); } - [ConditionalFact(Skip = "Issue#2266")] + // TPT does not have discriminator public override void Discriminator_used_when_projection_over_of_type() { - base.Discriminator_used_when_projection_over_of_type(); } - [ConditionalFact(Skip = "Issue#2266")] + // TPT does not have discriminator public override void Discriminator_with_cast_in_shadow_property() { - base.Discriminator_with_cast_in_shadow_property(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Member_access_on_intermediate_type_works() - { - base.Member_access_on_intermediate_type_works(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void OfType_Union_OfType() - { - base.OfType_Union_OfType(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void OfType_Union_subquery() - { - base.OfType_Union_subquery(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Setting_foreign_key_to_a_different_type_throws() - { - base.Setting_foreign_key_to_a_different_type_throws(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Subquery_OfType() - { - base.Subquery_OfType(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Union_entity_equality() - { - base.Union_entity_equality(); - } - - [ConditionalFact(Skip = "Issue#2266")] - public override void Union_siblings_with_duplicate_property_in_subquery() - { - base.Union_siblings_with_duplicate_property_in_subquery(); } } } diff --git a/test/EFCore.Relational.Specification.Tests/Query/TPTRelationshipsQueryTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/TPTRelationshipsQueryTestBase.cs index b8b2fefa817..92132f56b9f 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/TPTRelationshipsQueryTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/TPTRelationshipsQueryTestBase.cs @@ -13,230 +13,5 @@ protected TPTRelationshipsQueryTestBase(TFixture fixture) : base(fixture) { } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Changes_in_derived_related_entities_are_detected() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_reference_with_inheritance() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_reference_with_inheritance_reverse() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_self_reference_with_inheritance() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_self_reference_with_inheritance_reverse() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_reference_with_inheritance_with_filter() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_reference_with_inheritance_with_filter_reverse() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_reference_without_inheritance() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_reference_without_inheritance_reverse() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_reference_without_inheritance_with_filter() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_reference_without_inheritance_with_filter_reverse() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_collection_with_inheritance() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_collection_with_inheritance_reverse() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_collection_with_inheritance_with_filter() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_collection_with_inheritance_with_filter_reverse() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_collection_without_inheritance() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_collection_without_inheritance_reverse() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_collection_without_inheritance_with_filter() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_collection_without_inheritance_with_filter_reverse() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_reference_with_inheritance_on_derived1() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_reference_with_inheritance_on_derived2() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_reference_with_inheritance_on_derived4() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_reference_with_inheritance_on_derived_reverse() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_reference_with_inheritance_on_derived_with_filter1() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_reference_with_inheritance_on_derived_with_filter2() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_reference_with_inheritance_on_derived_with_filter4() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_reference_with_inheritance_on_derived_with_filter_reverse() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_reference_without_inheritance_on_derived1() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_reference_without_inheritance_on_derived2() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_reference_without_inheritance_on_derived_reverse() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_collection_with_inheritance_on_derived1() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_collection_with_inheritance_on_derived2() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_collection_with_inheritance_on_derived3() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Include_collection_with_inheritance_on_derived_reverse() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Nested_include_with_inheritance_reference_reference() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Nested_include_with_inheritance_reference_reference_on_base() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Nested_include_with_inheritance_reference_reference_reverse() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Nested_include_with_inheritance_reference_collection() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Nested_include_with_inheritance_reference_collection_on_base() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Nested_include_with_inheritance_reference_collection_reverse() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Nested_include_with_inheritance_collection_reference() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Nested_include_with_inheritance_collection_reference_reverse() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Nested_include_with_inheritance_collection_collection() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Nested_include_with_inheritance_collection_collection_reverse() - { - } - - [ConditionalFact(Skip = "Issue #2266")] - public override void Nested_include_collection_reference_on_non_entity_base() - { - } } } diff --git a/test/EFCore.Specification.Tests/Query/InheritanceQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/InheritanceQueryTestBase.cs index 551dddeadc3..6792e653f28 100644 --- a/test/EFCore.Specification.Tests/Query/InheritanceQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/InheritanceQueryTestBase.cs @@ -431,10 +431,6 @@ public virtual void Can_insert_update_delete() }); } - protected virtual void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) - { - } - [ConditionalFact(Skip = "Issue#16298")] public virtual void Union_siblings_with_duplicate_property_in_subquery() { @@ -559,6 +555,10 @@ public virtual void Member_access_on_intermediate_type_works() protected InheritanceContext CreateContext() => Fixture.CreateContext(); + protected virtual void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) + { + } + protected virtual bool EnforcesFkConstraints => true; protected virtual void ClearLog() diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs index aa765286fa9..c45a0c89f95 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs @@ -3987,10 +3987,10 @@ public override async Task Correlated_collections_inner_subquery_selector_refere await base.Correlated_collections_inner_subquery_selector_references_outer_qsre(async); AssertSql( - @"SELECT [g].[FullName], [g].[Nickname], [g].[SquadId], [t].[FullName], [t].[FullName0], [t].[Nickname], [t].[SquadId] + @"SELECT [g].[FullName], [g].[Nickname], [g].[SquadId], [t].[ReportName], [t].[OfficerName], [t].[Nickname], [t].[SquadId] FROM [Gears] AS [g] OUTER APPLY ( - SELECT [g0].[FullName], [g].[FullName] AS [FullName0], [g0].[Nickname], [g0].[SquadId] + SELECT [g0].[FullName] AS [ReportName], [g].[FullName] AS [OfficerName], [g0].[Nickname], [g0].[SquadId] FROM [Gears] AS [g0] WHERE ([g].[Nickname] = [g0].[LeaderNickname]) AND ([g].[SquadId] = [g0].[LeaderSquadId]) ) AS [t] @@ -4003,10 +4003,10 @@ public override async Task Correlated_collections_inner_subquery_predicate_refer await base.Correlated_collections_inner_subquery_predicate_references_outer_qsre(async); AssertSql( - @"SELECT [g].[FullName], [g].[Nickname], [g].[SquadId], [t].[FullName], [t].[Nickname], [t].[SquadId] + @"SELECT [g].[FullName], [g].[Nickname], [g].[SquadId], [t].[ReportName], [t].[Nickname], [t].[SquadId] FROM [Gears] AS [g] OUTER APPLY ( - SELECT [g0].[FullName], [g0].[Nickname], [g0].[SquadId] + SELECT [g0].[FullName] AS [ReportName], [g0].[Nickname], [g0].[SquadId] FROM [Gears] AS [g0] WHERE ([g].[FullName] <> N'Foo') AND (([g].[Nickname] = [g0].[LeaderNickname]) AND ([g].[SquadId] = [g0].[LeaderSquadId])) ) AS [t] diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindMiscellaneousQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindMiscellaneousQuerySqlServerTest.cs index 525c1f8bf6e..92e842c15fa 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindMiscellaneousQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindMiscellaneousQuerySqlServerTest.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; @@ -4451,13 +4451,13 @@ public override async Task Complex_nested_query_doesnt_try_binding_to_grandparen await base.Complex_nested_query_doesnt_try_binding_to_grandparent_when_parent_returns_complex_result(async); AssertSql( - @"SELECT [c].[CustomerID], [t].[c], [t].[CustomerID], [t].[OrderID] + @"SELECT [c].[CustomerID], [t].[InnerOrder], [t].[Id], [t].[OrderID] FROM [Customers] AS [c] OUTER APPLY ( SELECT ( SELECT COUNT(*) FROM [Orders] AS [o] - WHERE [c].[CustomerID] = [o].[CustomerID]) AS [c], [c].[CustomerID], [o0].[OrderID] + WHERE [c].[CustomerID] = [o].[CustomerID]) AS [InnerOrder], [c].[CustomerID] AS [Id], [o0].[OrderID] FROM [Orders] AS [o0] WHERE [c].[CustomerID] = [o0].[CustomerID] ) AS [t] diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindSelectQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindSelectQuerySqlServerTest.cs index 57fc1c1c949..96f85cfdca1 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindSelectQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/NorthwindSelectQuerySqlServerTest.cs @@ -325,12 +325,12 @@ public override void Select_nested_collection_multi_level() base.Select_nested_collection_multi_level(); AssertSql( - @"SELECT [c].[CustomerID], [t0].[OrderDate], [t0].[OrderID] + @"SELECT [c].[CustomerID], [t0].[Date], [t0].[OrderID] FROM [Customers] AS [c] LEFT JOIN ( - SELECT [t].[OrderDate], [t].[OrderID], [t].[CustomerID] + SELECT [t].[Date], [t].[OrderID], [t].[CustomerID] FROM ( - SELECT [o].[OrderDate], [o].[OrderID], [o].[CustomerID], ROW_NUMBER() OVER(PARTITION BY [o].[CustomerID] ORDER BY [o].[OrderID]) AS [row] + SELECT [o].[OrderDate] AS [Date], [o].[OrderID], [o].[CustomerID], ROW_NUMBER() OVER(PARTITION BY [o].[CustomerID] ORDER BY [o].[OrderID]) AS [row] FROM [Orders] AS [o] WHERE [o].[OrderID] < 10500 ) AS [t] diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs index 42b71fa451c..e3dea35c976 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/QueryBugsTest.cs @@ -6361,7 +6361,7 @@ private class Activity12456 #region Issue15137 [ConditionalFact] - public virtual async Task Run_something() + public virtual async Task Max_in_multi_level_nested_subquery() { using (CreateDatabase15137()) { @@ -6391,8 +6391,8 @@ public virtual async Task Run_something() }) .SingleAsync(); - AssertSql( - @"SELECT [t0].[Id], [t1].[Id], [t1].[Id0], [t1].[Id1], [t1].[c] + AssertSql( + @"SELECT [t0].[Id], [t1].[Id], [t1].[Id0], [t1].[Id1], [t1].[IsPastTradeDeadline] FROM ( SELECT TOP(2) [t].[Id] FROM [Trades] AS [t] @@ -6404,7 +6404,7 @@ SELECT MAX([d].[GameNumber]) FROM [DbGame] AS [d] WHERE [d2].[Id] IS NOT NULL AND ([d2].[Id] = [d].[SeasonId])), 0) > 10 THEN CAST(1 AS bit) ELSE CAST(0 AS bit) - END AS [c], [d0].[DbTradeId] + END AS [IsPastTradeDeadline], [d0].[DbTradeId] FROM [DbTradeAsset] AS [d0] INNER JOIN [DbContract] AS [d1] ON [d0].[ContractId] = [d1].[Id] LEFT JOIN [DbSeason] AS [d2] ON [d1].[SeasonId] = [d2].[Id] diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TPTInheritanceQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TPTInheritanceQuerySqlServerTest.cs index e45970c608f..cdde9a26c83 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TPTInheritanceQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TPTInheritanceQuerySqlServerTest.cs @@ -1,6 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Storage; using Xunit.Abstractions; // ReSharper disable InconsistentNaming @@ -14,5 +16,604 @@ public TPTInheritanceQuerySqlServerTest(TPTInheritanceQuerySqlServerFixture fixt Fixture.TestSqlLoggerFactory.Clear(); //Fixture.TestSqlLoggerFactory.SetTestOutputHelper(testOutputHelper); } + + public override void Byte_enum_value_constant_used_in_projection() + { + base.Byte_enum_value_constant_used_in_projection(); + + AssertSql( + @"SELECT CASE + WHEN [b].[IsFlightless] = CAST(1 AS bit) THEN CAST(0 AS tinyint) + ELSE CAST(1 AS tinyint) +END +FROM [Animals] AS [a] +INNER JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] +INNER JOIN [Kiwi] AS [k] ON [a].[Species] = [k].[Species]"); + } + + public override void Can_filter_all_animals() + { + base.Can_filter_all_animals(); + + AssertSql( + @"SELECT [a].[Species], [a].[CountryId], [a].[Name], [b].[EagleId], [b].[IsFlightless], [e].[Group], [k].[FoundOn], CASE + WHEN [e].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsEagle], CASE + WHEN [k].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsKiwi] +FROM [Animals] AS [a] +LEFT JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] +LEFT JOIN [Eagle] AS [e] ON [a].[Species] = [e].[Species] +LEFT JOIN [Kiwi] AS [k] ON [a].[Species] = [k].[Species] +WHERE [a].[Name] = N'Great spotted kiwi' +ORDER BY [a].[Species]"); + } + + public override void Can_include_animals() + { + base.Can_include_animals(); + + AssertSql( + @"SELECT [c].[Id], [c].[Name], [t].[Species], [t].[CountryId], [t].[Name], [t].[EagleId], [t].[IsFlightless], [t].[Group], [t].[FoundOn], [t].[IsEagle], [t].[IsKiwi] +FROM [Country] AS [c] +LEFT JOIN ( + SELECT [a].[Species], [a].[CountryId], [a].[Name], [b].[EagleId], [b].[IsFlightless], [e].[Group], [k].[FoundOn], CASE + WHEN [e].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsEagle], CASE + WHEN [k].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsKiwi] + FROM [Animals] AS [a] + LEFT JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] + LEFT JOIN [Eagle] AS [e] ON [a].[Species] = [e].[Species] + LEFT JOIN [Kiwi] AS [k] ON [a].[Species] = [k].[Species] +) AS [t] ON [c].[Id] = [t].[CountryId] +ORDER BY [c].[Name], [c].[Id], [t].[Species]"); + } + + public override void Can_include_prey() + { + base.Can_include_prey(); + + AssertSql( + @"SELECT [t].[Species], [t].[CountryId], [t].[Name], [t].[EagleId], [t].[IsFlightless], [t].[Group], [t0].[Species], [t0].[CountryId], [t0].[Name], [t0].[EagleId], [t0].[IsFlightless], [t0].[Group], [t0].[FoundOn], [t0].[IsEagle], [t0].[IsKiwi] +FROM ( + SELECT TOP(2) [a].[Species], [a].[CountryId], [a].[Name], [b].[EagleId], [b].[IsFlightless], [e].[Group] + FROM [Animals] AS [a] + INNER JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] + INNER JOIN [Eagle] AS [e] ON [a].[Species] = [e].[Species] +) AS [t] +LEFT JOIN ( + SELECT [a0].[Species], [a0].[CountryId], [a0].[Name], [b0].[EagleId], [b0].[IsFlightless], [e0].[Group], [k].[FoundOn], CASE + WHEN [e0].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsEagle], CASE + WHEN [k].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsKiwi] + FROM [Animals] AS [a0] + INNER JOIN [Birds] AS [b0] ON [a0].[Species] = [b0].[Species] + LEFT JOIN [Eagle] AS [e0] ON [a0].[Species] = [e0].[Species] + LEFT JOIN [Kiwi] AS [k] ON [a0].[Species] = [k].[Species] +) AS [t0] ON [t].[Species] = [t0].[EagleId] +ORDER BY [t].[Species], [t0].[Species]"); + } + + public override void Can_insert_update_delete() + { + base.Can_insert_update_delete(); + + AssertSql( + @"SELECT TOP(2) [c].[Id], [c].[Name] +FROM [Country] AS [c] +WHERE [c].[Id] = 1", + // + @"@p0='Apteryx owenii' (Nullable = false) (Size = 100) +@p1='1' +@p2='Little spotted kiwi' (Size = 4000) + +SET NOCOUNT ON; +INSERT INTO [Animals] ([Species], [CountryId], [Name]) +VALUES (@p0, @p1, @p2);", + // + @"@p0='Apteryx owenii' (Nullable = false) (Size = 100) +@p1=NULL (Size = 100) +@p2='True' + +SET NOCOUNT ON; +INSERT INTO [Birds] ([Species], [EagleId], [IsFlightless]) +VALUES (@p0, @p1, @p2);", + // + @"@p0='Apteryx owenii' (Nullable = false) (Size = 100) +@p1='0' (Size = 1) + +SET NOCOUNT ON; +INSERT INTO [Kiwi] ([Species], [FoundOn]) +VALUES (@p0, @p1);", + // + @"SELECT TOP(2) [a].[Species], [a].[CountryId], [a].[Name], [b].[EagleId], [b].[IsFlightless], [k].[FoundOn] +FROM [Animals] AS [a] +INNER JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] +INNER JOIN [Kiwi] AS [k] ON [a].[Species] = [k].[Species] +WHERE [a].[Species] LIKE N'%owenii'", + // + @"@p1='Apteryx owenii' (Nullable = false) (Size = 100) +@p0='Aquila chrysaetos canadensis' (Size = 100) + +SET NOCOUNT ON; +UPDATE [Birds] SET [EagleId] = @p0 +WHERE [Species] = @p1; +SELECT @@ROWCOUNT;", + // + @"SELECT TOP(2) [a].[Species], [a].[CountryId], [a].[Name], [b].[EagleId], [b].[IsFlightless], [k].[FoundOn] +FROM [Animals] AS [a] +INNER JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] +INNER JOIN [Kiwi] AS [k] ON [a].[Species] = [k].[Species] +WHERE [a].[Species] LIKE N'%owenii'", + // + @"@p0='Apteryx owenii' (Nullable = false) (Size = 100) + +SET NOCOUNT ON; +DELETE FROM [Animals] +WHERE [Species] = @p0; +SELECT @@ROWCOUNT;", + // + @"@p0='Apteryx owenii' (Nullable = false) (Size = 100) + +SET NOCOUNT ON; +DELETE FROM [Birds] +WHERE [Species] = @p0; +SELECT @@ROWCOUNT;", + // + @"@p0='Apteryx owenii' (Nullable = false) (Size = 100) + +SET NOCOUNT ON; +DELETE FROM [Kiwi] +WHERE [Species] = @p0; +SELECT @@ROWCOUNT;", + // + @"SELECT COUNT(*) +FROM [Animals] AS [a] +INNER JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] +INNER JOIN [Kiwi] AS [k] ON [a].[Species] = [k].[Species] +WHERE [a].[Species] LIKE N'%owenii'"); + } + + public override void Can_query_all_animals() + { + base.Can_query_all_animals(); + + AssertSql( + @"SELECT [a].[Species], [a].[CountryId], [a].[Name], [b].[EagleId], [b].[IsFlightless], [e].[Group], [k].[FoundOn], CASE + WHEN [e].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsEagle], CASE + WHEN [k].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsKiwi] +FROM [Animals] AS [a] +LEFT JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] +LEFT JOIN [Eagle] AS [e] ON [a].[Species] = [e].[Species] +LEFT JOIN [Kiwi] AS [k] ON [a].[Species] = [k].[Species] +ORDER BY [a].[Species]"); + } + + public override void Can_query_all_birds() + { + base.Can_query_all_birds(); + + AssertSql( + @"SELECT [a].[Species], [a].[CountryId], [a].[Name], [b].[EagleId], [b].[IsFlightless], [e].[Group], [k].[FoundOn], CASE + WHEN [e].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsEagle], CASE + WHEN [k].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsKiwi] +FROM [Animals] AS [a] +INNER JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] +LEFT JOIN [Eagle] AS [e] ON [a].[Species] = [e].[Species] +LEFT JOIN [Kiwi] AS [k] ON [a].[Species] = [k].[Species] +ORDER BY [a].[Species]"); + } + + public override void Can_query_all_plants() + { + base.Can_query_all_plants(); + + AssertSql( + @"SELECT [p].[Species], [p].[CountryId], [p].[Genus], [p].[Name], [r].[HasThorns], CASE + WHEN [d].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsDaisy], CASE + WHEN [r].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsRose] +FROM [Plants] AS [p] +LEFT JOIN [Flowers] AS [f] ON [p].[Species] = [f].[Species] +LEFT JOIN [Daisies] AS [d] ON [p].[Species] = [d].[Species] +LEFT JOIN [Roses] AS [r] ON [p].[Species] = [r].[Species] +ORDER BY [p].[Species]"); + } + + public override void Can_query_all_types_when_shared_column() + { + base.Can_query_all_types_when_shared_column(); + + AssertSql( + @"SELECT [d].[Id], [c].[CaffeineGrams], [c].[CokeCO2], [c].[SugarGrams], [l].[LiltCO2], [l].[SugarGrams], [t].[CaffeineGrams], [t].[HasMilk], CASE + WHEN [c].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsCoke], CASE + WHEN [l].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsLilt], CASE + WHEN [t].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsTea] +FROM [Drinks] AS [d] +LEFT JOIN [Coke] AS [c] ON [d].[Id] = [c].[Id] +LEFT JOIN [Lilt] AS [l] ON [d].[Id] = [l].[Id] +LEFT JOIN [Tea] AS [t] ON [d].[Id] = [t].[Id]"); + } + + public override void Can_query_just_kiwis() + { + base.Can_query_just_kiwis(); + + AssertSql( + @"SELECT TOP(2) [a].[Species], [a].[CountryId], [a].[Name], [b].[EagleId], [b].[IsFlightless], [k].[FoundOn] +FROM [Animals] AS [a] +INNER JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] +INNER JOIN [Kiwi] AS [k] ON [a].[Species] = [k].[Species]"); + } + + public override void Can_query_just_roses() + { + base.Can_query_just_roses(); + + AssertSql( + @"SELECT TOP(2) [p].[Species], [p].[CountryId], [p].[Genus], [p].[Name], [r].[HasThorns] +FROM [Plants] AS [p] +INNER JOIN [Flowers] AS [f] ON [p].[Species] = [f].[Species] +INNER JOIN [Roses] AS [r] ON [p].[Species] = [r].[Species]"); + } + + public override void Can_query_when_shared_column() + { + base.Can_query_when_shared_column(); + + AssertSql( + @"SELECT TOP(2) [d].[Id], [c].[CaffeineGrams], [c].[CokeCO2], [c].[SugarGrams] +FROM [Drinks] AS [d] +INNER JOIN [Coke] AS [c] ON [d].[Id] = [c].[Id]", + // + @"SELECT TOP(2) [d].[Id], [l].[LiltCO2], [l].[SugarGrams] +FROM [Drinks] AS [d] +INNER JOIN [Lilt] AS [l] ON [d].[Id] = [l].[Id]", + // + @"SELECT TOP(2) [d].[Id], [t].[CaffeineGrams], [t].[HasMilk] +FROM [Drinks] AS [d] +INNER JOIN [Tea] AS [t] ON [d].[Id] = [t].[Id]"); + } + + public override void Can_use_backwards_is_animal() + { + base.Can_use_backwards_is_animal(); + + AssertSql( + @"SELECT [a].[Species], [a].[CountryId], [a].[Name], [b].[EagleId], [b].[IsFlightless], [k].[FoundOn] +FROM [Animals] AS [a] +INNER JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] +INNER JOIN [Kiwi] AS [k] ON [a].[Species] = [k].[Species]"); + } + + public override void Can_use_backwards_of_type_animal() + { + base.Can_use_backwards_of_type_animal(); + + AssertSql(" "); + } + + public override void Can_use_is_kiwi() + { + base.Can_use_is_kiwi(); + + AssertSql( + @"SELECT [a].[Species], [a].[CountryId], [a].[Name], [b].[EagleId], [b].[IsFlightless], [e].[Group], [k].[FoundOn], CASE + WHEN [e].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsEagle], CASE + WHEN [k].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsKiwi] +FROM [Animals] AS [a] +LEFT JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] +LEFT JOIN [Eagle] AS [e] ON [a].[Species] = [e].[Species] +LEFT JOIN [Kiwi] AS [k] ON [a].[Species] = [k].[Species] +WHERE [k].[Species] IS NOT NULL"); + } + + public override void Can_use_is_kiwi_in_projection() + { + base.Can_use_is_kiwi_in_projection(); + + AssertSql( + @"SELECT CASE + WHEN [k].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END +FROM [Animals] AS [a] +LEFT JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] +LEFT JOIN [Eagle] AS [e] ON [a].[Species] = [e].[Species] +LEFT JOIN [Kiwi] AS [k] ON [a].[Species] = [k].[Species]"); + } + + public override void Can_use_is_kiwi_with_other_predicate() + { + base.Can_use_is_kiwi_with_other_predicate(); + + AssertSql( + @"SELECT [a].[Species], [a].[CountryId], [a].[Name], [b].[EagleId], [b].[IsFlightless], [e].[Group], [k].[FoundOn], CASE + WHEN [e].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsEagle], CASE + WHEN [k].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsKiwi] +FROM [Animals] AS [a] +LEFT JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] +LEFT JOIN [Eagle] AS [e] ON [a].[Species] = [e].[Species] +LEFT JOIN [Kiwi] AS [k] ON [a].[Species] = [k].[Species] +WHERE [k].[Species] IS NOT NULL AND ([a].[CountryId] = 1)"); + } + + public override void Can_use_of_type_animal() + { + base.Can_use_of_type_animal(); + + AssertSql( + @"SELECT [a].[Species], [a].[CountryId], [a].[Name], [b].[EagleId], [b].[IsFlightless], [e].[Group], [k].[FoundOn], CASE + WHEN [e].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsEagle], CASE + WHEN [k].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsKiwi] +FROM [Animals] AS [a] +LEFT JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] +LEFT JOIN [Eagle] AS [e] ON [a].[Species] = [e].[Species] +LEFT JOIN [Kiwi] AS [k] ON [a].[Species] = [k].[Species] +ORDER BY [a].[Species]"); + } + + public override void Can_use_of_type_bird() + { + base.Can_use_of_type_bird(); + + AssertSql( + @"SELECT [a].[Species], [a].[CountryId], [a].[Name], [b].[EagleId], [b].[IsFlightless], [e].[Group], [k].[FoundOn], CASE + WHEN [e].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsEagle], CASE + WHEN [k].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsKiwi] +FROM [Animals] AS [a] +LEFT JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] +LEFT JOIN [Eagle] AS [e] ON [a].[Species] = [e].[Species] +LEFT JOIN [Kiwi] AS [k] ON [a].[Species] = [k].[Species] +WHERE [e].[Species] IS NOT NULL OR [k].[Species] IS NOT NULL +ORDER BY [a].[Species]"); + } + + public override void Can_use_of_type_bird_first() + { + base.Can_use_of_type_bird_first(); + + AssertSql( + @"SELECT TOP(1) [a].[Species], [a].[CountryId], [a].[Name], [b].[EagleId], [b].[IsFlightless], [e].[Group], [k].[FoundOn], CASE + WHEN [e].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsEagle], CASE + WHEN [k].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsKiwi] +FROM [Animals] AS [a] +LEFT JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] +LEFT JOIN [Eagle] AS [e] ON [a].[Species] = [e].[Species] +LEFT JOIN [Kiwi] AS [k] ON [a].[Species] = [k].[Species] +WHERE [e].[Species] IS NOT NULL OR [k].[Species] IS NOT NULL +ORDER BY [a].[Species]"); + } + + public override void Can_use_of_type_bird_predicate() + { + base.Can_use_of_type_bird_predicate(); + + AssertSql( + @"SELECT [a].[Species], [a].[CountryId], [a].[Name], [b].[EagleId], [b].[IsFlightless], [e].[Group], [k].[FoundOn], CASE + WHEN [e].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsEagle], CASE + WHEN [k].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsKiwi] +FROM [Animals] AS [a] +LEFT JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] +LEFT JOIN [Eagle] AS [e] ON [a].[Species] = [e].[Species] +LEFT JOIN [Kiwi] AS [k] ON [a].[Species] = [k].[Species] +WHERE ([a].[CountryId] = 1) AND ([e].[Species] IS NOT NULL OR [k].[Species] IS NOT NULL) +ORDER BY [a].[Species]"); + } + + public override void Can_use_of_type_bird_with_projection() + { + base.Can_use_of_type_bird_with_projection(); + + AssertSql( + @"SELECT [b].[EagleId] +FROM [Animals] AS [a] +LEFT JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] +LEFT JOIN [Eagle] AS [e] ON [a].[Species] = [e].[Species] +LEFT JOIN [Kiwi] AS [k] ON [a].[Species] = [k].[Species] +WHERE [e].[Species] IS NOT NULL OR [k].[Species] IS NOT NULL"); + } + + public override void Can_use_of_type_kiwi() + { + base.Can_use_of_type_kiwi(); + + AssertSql( + @"SELECT [a].[Species], [a].[CountryId], [a].[Name], [b].[EagleId], [b].[IsFlightless], [k].[FoundOn], CASE + WHEN [k].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsKiwi] +FROM [Animals] AS [a] +LEFT JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] +LEFT JOIN [Eagle] AS [e] ON [a].[Species] = [e].[Species] +LEFT JOIN [Kiwi] AS [k] ON [a].[Species] = [k].[Species] +WHERE [k].[Species] IS NOT NULL"); + } + + public override void Can_use_of_type_kiwi_where_north_on_derived_property() + { + base.Can_use_of_type_kiwi_where_north_on_derived_property(); + + AssertSql( + @"SELECT [a].[Species], [a].[CountryId], [a].[Name], [b].[EagleId], [b].[IsFlightless], [k].[FoundOn], CASE + WHEN [k].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsKiwi] +FROM [Animals] AS [a] +LEFT JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] +LEFT JOIN [Eagle] AS [e] ON [a].[Species] = [e].[Species] +LEFT JOIN [Kiwi] AS [k] ON [a].[Species] = [k].[Species] +WHERE [k].[Species] IS NOT NULL AND ([k].[FoundOn] = CAST(0 AS tinyint))"); + } + + public override void Can_use_of_type_kiwi_where_south_on_derived_property() + { + base.Can_use_of_type_kiwi_where_south_on_derived_property(); + + AssertSql( + @"SELECT [a].[Species], [a].[CountryId], [a].[Name], [b].[EagleId], [b].[IsFlightless], [k].[FoundOn], CASE + WHEN [k].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsKiwi] +FROM [Animals] AS [a] +LEFT JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] +LEFT JOIN [Eagle] AS [e] ON [a].[Species] = [e].[Species] +LEFT JOIN [Kiwi] AS [k] ON [a].[Species] = [k].[Species] +WHERE [k].[Species] IS NOT NULL AND ([k].[FoundOn] = CAST(1 AS tinyint))"); + } + + public override void Can_use_of_type_rose() + { + base.Can_use_of_type_rose(); + + AssertSql( + @"SELECT [p].[Species], [p].[CountryId], [p].[Genus], [p].[Name], [r].[HasThorns], CASE + WHEN [r].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsRose] +FROM [Plants] AS [p] +LEFT JOIN [Flowers] AS [f] ON [p].[Species] = [f].[Species] +LEFT JOIN [Daisies] AS [d] ON [p].[Species] = [d].[Species] +LEFT JOIN [Roses] AS [r] ON [p].[Species] = [r].[Species] +WHERE [r].[Species] IS NOT NULL"); + } + + public override void Member_access_on_intermediate_type_works() + { + base.Member_access_on_intermediate_type_works(); + + AssertSql( + @"SELECT [a].[Name] +FROM [Animals] AS [a] +INNER JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] +INNER JOIN [Kiwi] AS [k] ON [a].[Species] = [k].[Species] +ORDER BY [a].[Name]"); + } + + public override void OfType_Union_OfType() + { + base.OfType_Union_OfType(); + + AssertSql(" "); + } + + public override void OfType_Union_subquery() + { + base.OfType_Union_subquery(); + + AssertSql(" "); + } + + public override void Setting_foreign_key_to_a_different_type_throws() + { + base.Setting_foreign_key_to_a_different_type_throws(); + + AssertSql( + @"SELECT TOP(2) [a].[Species], [a].[CountryId], [a].[Name], [b].[EagleId], [b].[IsFlightless], [k].[FoundOn] +FROM [Animals] AS [a] +INNER JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] +INNER JOIN [Kiwi] AS [k] ON [a].[Species] = [k].[Species]", + // + @"@p0='Haliaeetus leucocephalus' (Nullable = false) (Size = 100) +@p1='0' +@p2='Bald eagle' (Size = 4000) + +SET NOCOUNT ON; +INSERT INTO [Animals] ([Species], [CountryId], [Name]) +VALUES (@p0, @p1, @p2);"); + } + + public override void Subquery_OfType() + { + base.Subquery_OfType(); + + AssertSql( + @"@__p_0='5' + +SELECT DISTINCT [t].[Species], [t].[CountryId], [t].[Name], [t].[EagleId], [t].[IsFlightless], [t].[FoundOn], [t].[IsKiwi] +FROM ( + SELECT TOP(@__p_0) [a].[Species], [a].[CountryId], [a].[Name], [b].[EagleId], [b].[IsFlightless], [e].[Group], [k].[FoundOn], CASE + WHEN [e].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsEagle], CASE + WHEN [k].[Species] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsKiwi] + FROM [Animals] AS [a] + INNER JOIN [Birds] AS [b] ON [a].[Species] = [b].[Species] + LEFT JOIN [Eagle] AS [e] ON [a].[Species] = [e].[Species] + LEFT JOIN [Kiwi] AS [k] ON [a].[Species] = [k].[Species] +) AS [t] +WHERE [t].[IsKiwi] = CAST(1 AS bit)"); + } + + public override void Union_entity_equality() + { + base.Union_entity_equality(); + + AssertSql(" "); + } + + public override void Union_siblings_with_duplicate_property_in_subquery() + { + base.Union_siblings_with_duplicate_property_in_subquery(); + + AssertSql(" "); + } + + protected override void UseTransaction(DatabaseFacade facade, IDbContextTransaction transaction) + => facade.UseTransaction(transaction.GetDbTransaction()); + + private void AssertSql(params string[] expected) + => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); } } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TPTRelationshipsQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TPTRelationshipsQuerySqlServerTest.cs index d87c538eb59..bfe91888e2e 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TPTRelationshipsQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TPTRelationshipsQuerySqlServerTest.cs @@ -16,6 +16,1049 @@ public TPTRelationshipsQuerySqlServerTest( fixture.TestSqlLoggerFactory.Clear(); } + public override void Changes_in_derived_related_entities_are_detected() + { + base.Changes_in_derived_related_entities_are_detected(); + + AssertSql( + @"SELECT [t].[Id], [t].[Name], [t].[BaseId], [t].[IsDerivedInheritanceRelationshipEntity], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id0], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [t0].[Id], [t0].[BaseParentId], [t0].[Name], [t0].[DerivedProperty], [t0].[IsDerivedCollectionOnBase] +FROM ( + SELECT TOP(2) [b].[Id], [b].[Name], [d].[BaseId], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedInheritanceRelationshipEntity], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id] AS [Id0], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name] + FROM [BaseEntities] AS [b] + LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] + WHERE [b].[Name] = N'Derived1(4)' +) AS [t] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [t].[Id] = [b0].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d0] ON [t].[Id] = [d0].[DerivedInheritanceRelationshipEntityId] +LEFT JOIN ( + SELECT [b1].[Id], [b1].[BaseParentId], [b1].[Name], [d1].[DerivedProperty], CASE + WHEN [d1].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedCollectionOnBase] + FROM [BaseCollectionsOnBase] AS [b1] + LEFT JOIN [DerivedCollectionsOnBase] AS [d1] ON [b1].[Id] = [d1].[Id] +) AS [t0] ON [t].[Id] = [t0].[BaseParentId] +ORDER BY [t].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [t0].[Id]"); + } + + public override void Include_collection_without_inheritance() + { + base.Include_collection_without_inheritance(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsDerivedInheritanceRelationshipEntity], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [c].[Id], [c].[Name], [c].[ParentId] +FROM [BaseEntities] AS [b] +LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d0] ON [b].[Id] = [d0].[DerivedInheritanceRelationshipEntityId] +LEFT JOIN [CollectionsOnBase] AS [c] ON [b].[Id] = [c].[ParentId] +ORDER BY [b].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [c].[Id]"); + } + + public override void Include_collection_without_inheritance_reverse() + { + base.Include_collection_without_inheritance_reverse(); + + AssertSql( + @"SELECT [c].[Id], [c].[Name], [c].[ParentId], [t].[Id], [t].[Name], [t].[BaseId], [t].[IsDerivedInheritanceRelationshipEntity], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name] +FROM [CollectionsOnBase] AS [c] +LEFT JOIN ( + SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedInheritanceRelationshipEntity], [b].[Id] AS [Id0], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id] AS [Id1], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name] + FROM [BaseEntities] AS [b] + LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +) AS [t] ON [c].[ParentId] = [t].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [t].[Id] = [b0].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d0] ON [t].[Id] = [d0].[DerivedInheritanceRelationshipEntityId] +ORDER BY [c].[Id], [t].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id]"); + } + + public override void Include_collection_without_inheritance_with_filter() + { + base.Include_collection_without_inheritance_with_filter(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsDerivedInheritanceRelationshipEntity], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [c].[Id], [c].[Name], [c].[ParentId] +FROM [BaseEntities] AS [b] +LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d0] ON [b].[Id] = [d0].[DerivedInheritanceRelationshipEntityId] +LEFT JOIN [CollectionsOnBase] AS [c] ON [b].[Id] = [c].[ParentId] +WHERE ([b].[Name] <> N'Bar') OR [b].[Name] IS NULL +ORDER BY [b].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [c].[Id]"); + } + + public override void Include_collection_without_inheritance_with_filter_reverse() + { + base.Include_collection_without_inheritance_with_filter_reverse(); + + AssertSql( + @"SELECT [c].[Id], [c].[Name], [c].[ParentId], [t].[Id], [t].[Name], [t].[BaseId], [t].[IsDerivedInheritanceRelationshipEntity], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name] +FROM [CollectionsOnBase] AS [c] +LEFT JOIN ( + SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedInheritanceRelationshipEntity], [b].[Id] AS [Id0], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id] AS [Id1], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name] + FROM [BaseEntities] AS [b] + LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +) AS [t] ON [c].[ParentId] = [t].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [t].[Id] = [b0].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d0] ON [t].[Id] = [d0].[DerivedInheritanceRelationshipEntityId] +WHERE ([c].[Name] <> N'Bar') OR [c].[Name] IS NULL +ORDER BY [c].[Id], [t].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id]"); + } + + public override void Include_collection_with_inheritance() + { + base.Include_collection_with_inheritance(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsDerivedInheritanceRelationshipEntity], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[DerivedProperty], [t].[IsDerivedCollectionOnBase] +FROM [BaseEntities] AS [b] +LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d0] ON [b].[Id] = [d0].[DerivedInheritanceRelationshipEntityId] +LEFT JOIN ( + SELECT [b1].[Id], [b1].[BaseParentId], [b1].[Name], [d1].[DerivedProperty], CASE + WHEN [d1].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedCollectionOnBase] + FROM [BaseCollectionsOnBase] AS [b1] + LEFT JOIN [DerivedCollectionsOnBase] AS [d1] ON [b1].[Id] = [d1].[Id] +) AS [t] ON [b].[Id] = [t].[BaseParentId] +ORDER BY [b].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [t].[Id]"); + } + + public override void Include_collection_with_inheritance_on_derived1() + { + base.Include_collection_with_inheritance_on_derived1(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[DerivedProperty], [t].[IsDerivedCollectionOnBase] +FROM [BaseEntities] AS [b] +INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d0] ON [b].[Id] = [d0].[DerivedInheritanceRelationshipEntityId] +LEFT JOIN ( + SELECT [b1].[Id], [b1].[BaseParentId], [b1].[Name], [d1].[DerivedProperty], CASE + WHEN [d1].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedCollectionOnBase] + FROM [BaseCollectionsOnBase] AS [b1] + LEFT JOIN [DerivedCollectionsOnBase] AS [d1] ON [b1].[Id] = [d1].[Id] +) AS [t] ON [b].[Id] = [t].[BaseParentId] +ORDER BY [b].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [t].[Id]"); + } + + public override void Include_collection_with_inheritance_on_derived2() + { + base.Include_collection_with_inheritance_on_derived2(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [t].[Id], [t].[Name], [t].[ParentId], [t].[DerivedInheritanceRelationshipEntityId], [t].[IsDerivedCollectionOnDerived] +FROM [BaseEntities] AS [b] +INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d0] ON [b].[Id] = [d0].[DerivedInheritanceRelationshipEntityId] +LEFT JOIN ( + SELECT [b1].[Id], [b1].[Name], [b1].[ParentId], [d1].[DerivedInheritanceRelationshipEntityId], CASE + WHEN [d1].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedCollectionOnDerived] + FROM [BaseCollectionsOnDerived] AS [b1] + LEFT JOIN [DerivedCollectionsOnDerived] AS [d1] ON [b1].[Id] = [d1].[Id] +) AS [t] ON [b].[Id] = [t].[ParentId] +ORDER BY [b].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [t].[Id]"); + } + + public override void Include_collection_with_inheritance_on_derived3() + { + base.Include_collection_with_inheritance_on_derived3(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [t].[Id], [t].[Name], [t].[ParentId], [t].[DerivedInheritanceRelationshipEntityId] +FROM [BaseEntities] AS [b] +INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d0] ON [b].[Id] = [d0].[DerivedInheritanceRelationshipEntityId] +LEFT JOIN ( + SELECT [b1].[Id], [b1].[Name], [b1].[ParentId], [d1].[DerivedInheritanceRelationshipEntityId] + FROM [BaseCollectionsOnDerived] AS [b1] + INNER JOIN [DerivedCollectionsOnDerived] AS [d1] ON [b1].[Id] = [d1].[Id] +) AS [t] ON [b].[Id] = [t].[DerivedInheritanceRelationshipEntityId] +ORDER BY [b].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [t].[Id]"); + } + + public override void Include_collection_with_inheritance_on_derived_reverse() + { + base.Include_collection_with_inheritance_on_derived_reverse(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [b].[ParentId], [d].[DerivedInheritanceRelationshipEntityId], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsDerivedCollectionOnDerived], [t].[Id], [t].[Name], [t].[BaseId], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +FROM [BaseCollectionsOnDerived] AS [b] +LEFT JOIN [DerivedCollectionsOnDerived] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN ( + SELECT [b0].[Id], [b0].[Name], [d0].[BaseId], [b0].[Id] AS [Id0], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [d0].[Id] AS [Id1], [d0].[OwnedReferenceOnDerived_Id], [d0].[OwnedReferenceOnDerived_Name] + FROM [BaseEntities] AS [b0] + INNER JOIN [DerivedEntities] AS [d0] ON [b0].[Id] = [d0].[Id] +) AS [t] ON [b].[ParentId] = [t].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [t].[Id] = [b1].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d1] ON [t].[Id] = [d1].[DerivedInheritanceRelationshipEntityId] +ORDER BY [b].[Id], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id]"); + } + + public override void Include_collection_with_inheritance_reverse() + { + base.Include_collection_with_inheritance_reverse(); + + AssertSql( + @"SELECT [b].[Id], [b].[BaseParentId], [b].[Name], [d].[DerivedProperty], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsDerivedCollectionOnBase], [t].[Id], [t].[Name], [t].[BaseId], [t].[IsDerivedInheritanceRelationshipEntity], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +FROM [BaseCollectionsOnBase] AS [b] +LEFT JOIN [DerivedCollectionsOnBase] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN ( + SELECT [b0].[Id], [b0].[Name], [d0].[BaseId], CASE + WHEN [d0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedInheritanceRelationshipEntity], [b0].[Id] AS [Id0], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [d0].[Id] AS [Id1], [d0].[OwnedReferenceOnDerived_Id], [d0].[OwnedReferenceOnDerived_Name] + FROM [BaseEntities] AS [b0] + LEFT JOIN [DerivedEntities] AS [d0] ON [b0].[Id] = [d0].[Id] +) AS [t] ON [b].[BaseParentId] = [t].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [t].[Id] = [b1].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d1] ON [t].[Id] = [d1].[DerivedInheritanceRelationshipEntityId] +ORDER BY [b].[Id], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id]"); + } + + public override void Include_collection_with_inheritance_with_filter() + { + base.Include_collection_with_inheritance_with_filter(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsDerivedInheritanceRelationshipEntity], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[DerivedProperty], [t].[IsDerivedCollectionOnBase] +FROM [BaseEntities] AS [b] +LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d0] ON [b].[Id] = [d0].[DerivedInheritanceRelationshipEntityId] +LEFT JOIN ( + SELECT [b1].[Id], [b1].[BaseParentId], [b1].[Name], [d1].[DerivedProperty], CASE + WHEN [d1].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedCollectionOnBase] + FROM [BaseCollectionsOnBase] AS [b1] + LEFT JOIN [DerivedCollectionsOnBase] AS [d1] ON [b1].[Id] = [d1].[Id] +) AS [t] ON [b].[Id] = [t].[BaseParentId] +WHERE ([b].[Name] <> N'Bar') OR [b].[Name] IS NULL +ORDER BY [b].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [t].[Id]"); + } + + public override void Include_collection_with_inheritance_with_filter_reverse() + { + base.Include_collection_with_inheritance_with_filter_reverse(); + + AssertSql( + @"SELECT [b].[Id], [b].[BaseParentId], [b].[Name], [d].[DerivedProperty], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsDerivedCollectionOnBase], [t].[Id], [t].[Name], [t].[BaseId], [t].[IsDerivedInheritanceRelationshipEntity], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +FROM [BaseCollectionsOnBase] AS [b] +LEFT JOIN [DerivedCollectionsOnBase] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN ( + SELECT [b0].[Id], [b0].[Name], [d0].[BaseId], CASE + WHEN [d0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedInheritanceRelationshipEntity], [b0].[Id] AS [Id0], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [d0].[Id] AS [Id1], [d0].[OwnedReferenceOnDerived_Id], [d0].[OwnedReferenceOnDerived_Name] + FROM [BaseEntities] AS [b0] + LEFT JOIN [DerivedEntities] AS [d0] ON [b0].[Id] = [d0].[Id] +) AS [t] ON [b].[BaseParentId] = [t].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [t].[Id] = [b1].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d1] ON [t].[Id] = [d1].[DerivedInheritanceRelationshipEntityId] +WHERE ([b].[Name] <> N'Bar') OR [b].[Name] IS NULL +ORDER BY [b].[Id], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id]"); + } + + public override void Include_reference_without_inheritance() + { + base.Include_reference_without_inheritance(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsDerivedInheritanceRelationshipEntity], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [r].[Id], [r].[Name], [r].[ParentId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name] +FROM [BaseEntities] AS [b] +LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN [ReferencesOnBase] AS [r] ON [b].[Id] = [r].[ParentId] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d0] ON [b].[Id] = [d0].[DerivedInheritanceRelationshipEntityId] +ORDER BY [b].[Id], [r].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id]"); + } + + public override void Include_reference_without_inheritance_on_derived1() + { + base.Include_reference_without_inheritance_on_derived1(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [r].[Id], [r].[Name], [r].[ParentId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name] +FROM [BaseEntities] AS [b] +INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN [ReferencesOnBase] AS [r] ON [b].[Id] = [r].[ParentId] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d0] ON [b].[Id] = [d0].[DerivedInheritanceRelationshipEntityId] +ORDER BY [b].[Id], [r].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id]"); + } + + public override void Include_reference_without_inheritance_on_derived2() + { + base.Include_reference_without_inheritance_on_derived2(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [r].[Id], [r].[Name], [r].[ParentId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name] +FROM [BaseEntities] AS [b] +INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN [ReferencesOnDerived] AS [r] ON [b].[Id] = [r].[ParentId] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d0] ON [b].[Id] = [d0].[DerivedInheritanceRelationshipEntityId] +ORDER BY [b].[Id], [r].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id]"); + } + + public override void Include_reference_without_inheritance_on_derived_reverse() + { + base.Include_reference_without_inheritance_on_derived_reverse(); + + AssertSql( + @"SELECT [r].[Id], [r].[Name], [r].[ParentId], [t].[Id], [t].[Name], [t].[BaseId], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name] +FROM [ReferencesOnDerived] AS [r] +LEFT JOIN ( + SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[Id] AS [Id0], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id] AS [Id1], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name] + FROM [BaseEntities] AS [b] + INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +) AS [t] ON [r].[ParentId] = [t].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [t].[Id] = [b0].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d0] ON [t].[Id] = [d0].[DerivedInheritanceRelationshipEntityId] +ORDER BY [r].[Id], [t].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id]"); + } + + public override void Include_reference_without_inheritance_reverse() + { + base.Include_reference_without_inheritance_reverse(); + + AssertSql( + @"SELECT [r].[Id], [r].[Name], [r].[ParentId], [t].[Id], [t].[Name], [t].[BaseId], [t].[IsDerivedInheritanceRelationshipEntity], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name] +FROM [ReferencesOnBase] AS [r] +LEFT JOIN ( + SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedInheritanceRelationshipEntity], [b].[Id] AS [Id0], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id] AS [Id1], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name] + FROM [BaseEntities] AS [b] + LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +) AS [t] ON [r].[ParentId] = [t].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [t].[Id] = [b0].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d0] ON [t].[Id] = [d0].[DerivedInheritanceRelationshipEntityId] +ORDER BY [r].[Id], [t].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id]"); + } + + public override void Include_reference_without_inheritance_with_filter() + { + base.Include_reference_without_inheritance_with_filter(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsDerivedInheritanceRelationshipEntity], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [r].[Id], [r].[Name], [r].[ParentId], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name] +FROM [BaseEntities] AS [b] +LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN [ReferencesOnBase] AS [r] ON [b].[Id] = [r].[ParentId] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d0] ON [b].[Id] = [d0].[DerivedInheritanceRelationshipEntityId] +WHERE ([b].[Name] <> N'Bar') OR [b].[Name] IS NULL +ORDER BY [b].[Id], [r].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id]"); + } + + public override void Include_reference_without_inheritance_with_filter_reverse() + { + base.Include_reference_without_inheritance_with_filter_reverse(); + + AssertSql( + @"SELECT [r].[Id], [r].[Name], [r].[ParentId], [t].[Id], [t].[Name], [t].[BaseId], [t].[IsDerivedInheritanceRelationshipEntity], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name] +FROM [ReferencesOnBase] AS [r] +LEFT JOIN ( + SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedInheritanceRelationshipEntity], [b].[Id] AS [Id0], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id] AS [Id1], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name] + FROM [BaseEntities] AS [b] + LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +) AS [t] ON [r].[ParentId] = [t].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [t].[Id] = [b0].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d0] ON [t].[Id] = [d0].[DerivedInheritanceRelationshipEntityId] +WHERE ([r].[Name] <> N'Bar') OR [r].[Name] IS NULL +ORDER BY [r].[Id], [t].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id]"); + } + + public override void Include_reference_with_inheritance() + { + base.Include_reference_with_inheritance(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsDerivedInheritanceRelationshipEntity], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[IsDerivedReferenceOnBase], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +FROM [BaseEntities] AS [b] +LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN ( + SELECT [b0].[Id], [b0].[BaseParentId], [b0].[Name], CASE + WHEN [d0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedReferenceOnBase] + FROM [BaseReferencesOnBase] AS [b0] + LEFT JOIN [DerivedReferencesOnBase] AS [d0] ON [b0].[Id] = [d0].[Id] +) AS [t] ON [b].[Id] = [t].[BaseParentId] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b].[Id] = [b1].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d1] ON [b].[Id] = [d1].[DerivedInheritanceRelationshipEntityId] +ORDER BY [b].[Id], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id]"); + } + + public override void Include_reference_with_inheritance_on_derived1() + { + base.Include_reference_with_inheritance_on_derived1(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[IsDerivedReferenceOnBase], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +FROM [BaseEntities] AS [b] +INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN ( + SELECT [b0].[Id], [b0].[BaseParentId], [b0].[Name], CASE + WHEN [d0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedReferenceOnBase] + FROM [BaseReferencesOnBase] AS [b0] + LEFT JOIN [DerivedReferencesOnBase] AS [d0] ON [b0].[Id] = [d0].[Id] +) AS [t] ON [b].[Id] = [t].[BaseParentId] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b].[Id] = [b1].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d1] ON [b].[Id] = [d1].[DerivedInheritanceRelationshipEntityId] +ORDER BY [b].[Id], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id]"); + } + + public override void Include_reference_with_inheritance_on_derived2() + { + base.Include_reference_with_inheritance_on_derived2(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[DerivedInheritanceRelationshipEntityId], [t].[IsDerivedReferenceOnDerived], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +FROM [BaseEntities] AS [b] +INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN ( + SELECT [b0].[Id], [b0].[BaseParentId], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], CASE + WHEN [d0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedReferenceOnDerived] + FROM [BaseReferencesOnDerived] AS [b0] + LEFT JOIN [DerivedReferencesOnDerived] AS [d0] ON [b0].[Id] = [d0].[Id] +) AS [t] ON [b].[Id] = [t].[BaseParentId] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b].[Id] = [b1].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d1] ON [b].[Id] = [d1].[DerivedInheritanceRelationshipEntityId] +ORDER BY [b].[Id], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id]"); + } + + public override void Include_reference_with_inheritance_on_derived4() + { + base.Include_reference_with_inheritance_on_derived4(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[DerivedInheritanceRelationshipEntityId], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +FROM [BaseEntities] AS [b] +INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN ( + SELECT [b0].[Id], [b0].[BaseParentId], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId] + FROM [BaseReferencesOnDerived] AS [b0] + INNER JOIN [DerivedReferencesOnDerived] AS [d0] ON [b0].[Id] = [d0].[Id] +) AS [t] ON [b].[Id] = [t].[DerivedInheritanceRelationshipEntityId] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b].[Id] = [b1].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d1] ON [b].[Id] = [d1].[DerivedInheritanceRelationshipEntityId] +ORDER BY [b].[Id], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id]"); + } + + public override void Include_reference_with_inheritance_on_derived_reverse() + { + base.Include_reference_with_inheritance_on_derived_reverse(); + + AssertSql( + @"SELECT [b].[Id], [b].[BaseParentId], [b].[Name], [d].[DerivedInheritanceRelationshipEntityId], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsDerivedReferenceOnDerived], [t].[Id], [t].[Name], [t].[BaseId], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +FROM [BaseReferencesOnDerived] AS [b] +LEFT JOIN [DerivedReferencesOnDerived] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN ( + SELECT [b0].[Id], [b0].[Name], [d0].[BaseId], [b0].[Id] AS [Id0], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [d0].[Id] AS [Id1], [d0].[OwnedReferenceOnDerived_Id], [d0].[OwnedReferenceOnDerived_Name] + FROM [BaseEntities] AS [b0] + INNER JOIN [DerivedEntities] AS [d0] ON [b0].[Id] = [d0].[Id] +) AS [t] ON [b].[BaseParentId] = [t].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [t].[Id] = [b1].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d1] ON [t].[Id] = [d1].[DerivedInheritanceRelationshipEntityId] +ORDER BY [b].[Id], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id]"); + } + + public override void Include_reference_with_inheritance_on_derived_with_filter1() + { + base.Include_reference_with_inheritance_on_derived_with_filter1(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[IsDerivedReferenceOnBase], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +FROM [BaseEntities] AS [b] +INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN ( + SELECT [b0].[Id], [b0].[BaseParentId], [b0].[Name], CASE + WHEN [d0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedReferenceOnBase] + FROM [BaseReferencesOnBase] AS [b0] + LEFT JOIN [DerivedReferencesOnBase] AS [d0] ON [b0].[Id] = [d0].[Id] +) AS [t] ON [b].[Id] = [t].[BaseParentId] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b].[Id] = [b1].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d1] ON [b].[Id] = [d1].[DerivedInheritanceRelationshipEntityId] +WHERE ([b].[Name] <> N'Bar') OR [b].[Name] IS NULL +ORDER BY [b].[Id], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id]"); + } + + public override void Include_reference_with_inheritance_on_derived_with_filter2() + { + base.Include_reference_with_inheritance_on_derived_with_filter2(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[DerivedInheritanceRelationshipEntityId], [t].[IsDerivedReferenceOnDerived], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +FROM [BaseEntities] AS [b] +INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN ( + SELECT [b0].[Id], [b0].[BaseParentId], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], CASE + WHEN [d0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedReferenceOnDerived] + FROM [BaseReferencesOnDerived] AS [b0] + LEFT JOIN [DerivedReferencesOnDerived] AS [d0] ON [b0].[Id] = [d0].[Id] +) AS [t] ON [b].[Id] = [t].[BaseParentId] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b].[Id] = [b1].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d1] ON [b].[Id] = [d1].[DerivedInheritanceRelationshipEntityId] +WHERE ([b].[Name] <> N'Bar') OR [b].[Name] IS NULL +ORDER BY [b].[Id], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id]"); + } + + public override void Include_reference_with_inheritance_on_derived_with_filter4() + { + base.Include_reference_with_inheritance_on_derived_with_filter4(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[DerivedInheritanceRelationshipEntityId], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +FROM [BaseEntities] AS [b] +INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN ( + SELECT [b0].[Id], [b0].[BaseParentId], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId] + FROM [BaseReferencesOnDerived] AS [b0] + INNER JOIN [DerivedReferencesOnDerived] AS [d0] ON [b0].[Id] = [d0].[Id] +) AS [t] ON [b].[Id] = [t].[DerivedInheritanceRelationshipEntityId] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b].[Id] = [b1].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d1] ON [b].[Id] = [d1].[DerivedInheritanceRelationshipEntityId] +WHERE ([b].[Name] <> N'Bar') OR [b].[Name] IS NULL +ORDER BY [b].[Id], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id]"); + } + + public override void Include_reference_with_inheritance_on_derived_with_filter_reverse() + { + base.Include_reference_with_inheritance_on_derived_with_filter_reverse(); + + AssertSql( + @"SELECT [b].[Id], [b].[BaseParentId], [b].[Name], [d].[DerivedInheritanceRelationshipEntityId], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsDerivedReferenceOnDerived], [t].[Id], [t].[Name], [t].[BaseId], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +FROM [BaseReferencesOnDerived] AS [b] +LEFT JOIN [DerivedReferencesOnDerived] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN ( + SELECT [b0].[Id], [b0].[Name], [d0].[BaseId], [b0].[Id] AS [Id0], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [d0].[Id] AS [Id1], [d0].[OwnedReferenceOnDerived_Id], [d0].[OwnedReferenceOnDerived_Name] + FROM [BaseEntities] AS [b0] + INNER JOIN [DerivedEntities] AS [d0] ON [b0].[Id] = [d0].[Id] +) AS [t] ON [b].[BaseParentId] = [t].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [t].[Id] = [b1].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d1] ON [t].[Id] = [d1].[DerivedInheritanceRelationshipEntityId] +WHERE ([b].[Name] <> N'Bar') OR [b].[Name] IS NULL +ORDER BY [b].[Id], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id]"); + } + + public override void Include_reference_with_inheritance_reverse() + { + base.Include_reference_with_inheritance_reverse(); + + AssertSql( + @"SELECT [b].[Id], [b].[BaseParentId], [b].[Name], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsDerivedReferenceOnBase], [t].[Id], [t].[Name], [t].[BaseId], [t].[IsDerivedInheritanceRelationshipEntity], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +FROM [BaseReferencesOnBase] AS [b] +LEFT JOIN [DerivedReferencesOnBase] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN ( + SELECT [b0].[Id], [b0].[Name], [d0].[BaseId], CASE + WHEN [d0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedInheritanceRelationshipEntity], [b0].[Id] AS [Id0], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [d0].[Id] AS [Id1], [d0].[OwnedReferenceOnDerived_Id], [d0].[OwnedReferenceOnDerived_Name] + FROM [BaseEntities] AS [b0] + LEFT JOIN [DerivedEntities] AS [d0] ON [b0].[Id] = [d0].[Id] +) AS [t] ON [b].[BaseParentId] = [t].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [t].[Id] = [b1].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d1] ON [t].[Id] = [d1].[DerivedInheritanceRelationshipEntityId] +ORDER BY [b].[Id], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id]"); + } + + public override void Include_reference_with_inheritance_with_filter() + { + base.Include_reference_with_inheritance_with_filter(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsDerivedInheritanceRelationshipEntity], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[IsDerivedReferenceOnBase], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +FROM [BaseEntities] AS [b] +LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN ( + SELECT [b0].[Id], [b0].[BaseParentId], [b0].[Name], CASE + WHEN [d0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedReferenceOnBase] + FROM [BaseReferencesOnBase] AS [b0] + LEFT JOIN [DerivedReferencesOnBase] AS [d0] ON [b0].[Id] = [d0].[Id] +) AS [t] ON [b].[Id] = [t].[BaseParentId] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b].[Id] = [b1].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d1] ON [b].[Id] = [d1].[DerivedInheritanceRelationshipEntityId] +WHERE ([b].[Name] <> N'Bar') OR [b].[Name] IS NULL +ORDER BY [b].[Id], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id]"); + } + + public override void Include_reference_with_inheritance_with_filter_reverse() + { + base.Include_reference_with_inheritance_with_filter_reverse(); + + AssertSql( + @"SELECT [b].[Id], [b].[BaseParentId], [b].[Name], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsDerivedReferenceOnBase], [t].[Id], [t].[Name], [t].[BaseId], [t].[IsDerivedInheritanceRelationshipEntity], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +FROM [BaseReferencesOnBase] AS [b] +LEFT JOIN [DerivedReferencesOnBase] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN ( + SELECT [b0].[Id], [b0].[Name], [d0].[BaseId], CASE + WHEN [d0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedInheritanceRelationshipEntity], [b0].[Id] AS [Id0], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [d0].[Id] AS [Id1], [d0].[OwnedReferenceOnDerived_Id], [d0].[OwnedReferenceOnDerived_Name] + FROM [BaseEntities] AS [b0] + LEFT JOIN [DerivedEntities] AS [d0] ON [b0].[Id] = [d0].[Id] +) AS [t] ON [b].[BaseParentId] = [t].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [t].[Id] = [b1].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d1] ON [t].[Id] = [d1].[DerivedInheritanceRelationshipEntityId] +WHERE ([b].[Name] <> N'Bar') OR [b].[Name] IS NULL +ORDER BY [b].[Id], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id]"); + } + + public override void Include_self_reference_with_inheritance() + { + base.Include_self_reference_with_inheritance(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsDerivedInheritanceRelationshipEntity], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[Name], [t].[BaseId], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [b2].[BaseInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [d2].[DerivedInheritanceRelationshipEntityId], [d2].[Id], [d2].[Name] +FROM [BaseEntities] AS [b] +LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN ( + SELECT [b0].[Id], [b0].[Name], [d0].[BaseId], [b0].[Id] AS [Id0], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [d0].[Id] AS [Id1], [d0].[OwnedReferenceOnDerived_Id], [d0].[OwnedReferenceOnDerived_Name] + FROM [BaseEntities] AS [b0] + INNER JOIN [DerivedEntities] AS [d0] ON [b0].[Id] = [d0].[Id] +) AS [t] ON [b].[Id] = [t].[BaseId] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b].[Id] = [b1].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d1] ON [b].[Id] = [d1].[DerivedInheritanceRelationshipEntityId] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b2] ON [t].[Id] = [b2].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d2] ON [t].[Id] = [d2].[DerivedInheritanceRelationshipEntityId] +ORDER BY [b].[Id], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [b2].[BaseInheritanceRelationshipEntityId], [b2].[Id], [d2].[DerivedInheritanceRelationshipEntityId], [d2].[Id]"); + } + + public override void Include_self_reference_with_inheritance_reverse() + { + base.Include_self_reference_with_inheritance_reverse(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[Name], [t].[BaseId], [t].[IsDerivedInheritanceRelationshipEntity], [t].[Id0], [t].[OwnedReferenceOnBase_Id], [t].[OwnedReferenceOnBase_Name], [t].[Id1], [t].[OwnedReferenceOnDerived_Id], [t].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [b2].[BaseInheritanceRelationshipEntityId], [b2].[Id], [b2].[Name], [d2].[DerivedInheritanceRelationshipEntityId], [d2].[Id], [d2].[Name] +FROM [BaseEntities] AS [b] +INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN ( + SELECT [b0].[Id], [b0].[Name], [d0].[BaseId], CASE + WHEN [d0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedInheritanceRelationshipEntity], [b0].[Id] AS [Id0], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [d0].[Id] AS [Id1], [d0].[OwnedReferenceOnDerived_Id], [d0].[OwnedReferenceOnDerived_Name] + FROM [BaseEntities] AS [b0] + LEFT JOIN [DerivedEntities] AS [d0] ON [b0].[Id] = [d0].[Id] +) AS [t] ON [d].[BaseId] = [t].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b].[Id] = [b1].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d1] ON [b].[Id] = [d1].[DerivedInheritanceRelationshipEntityId] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b2] ON [t].[Id] = [b2].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d2] ON [t].[Id] = [d2].[DerivedInheritanceRelationshipEntityId] +ORDER BY [b].[Id], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [b2].[BaseInheritanceRelationshipEntityId], [b2].[Id], [d2].[DerivedInheritanceRelationshipEntityId], [d2].[Id]"); + } + + public override void Nested_include_collection_reference_on_non_entity_base() + { + base.Nested_include_collection_reference_on_non_entity_base(); + + AssertSql( + @"SELECT [r].[Id], [r].[Name], [t].[Id], [t].[Name], [t].[ReferenceId], [t].[ReferencedEntityId], [t].[Id0], [t].[Name0] +FROM [ReferencedEntities] AS [r] +LEFT JOIN ( + SELECT [p].[Id], [p].[Name], [p].[ReferenceId], [p].[ReferencedEntityId], [r0].[Id] AS [Id0], [r0].[Name] AS [Name0] + FROM [PrincipalEntities] AS [p] + LEFT JOIN [ReferencedEntities] AS [r0] ON [p].[ReferenceId] = [r0].[Id] +) AS [t] ON [r].[Id] = [t].[ReferencedEntityId] +ORDER BY [r].[Id], [t].[Id], [t].[Id0]"); + } + + public override void Nested_include_with_inheritance_collection_collection() + { + base.Nested_include_with_inheritance_collection_collection(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsDerivedInheritanceRelationshipEntity], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [t0].[Id], [t0].[BaseParentId], [t0].[Name], [t0].[DerivedProperty], [t0].[IsDerivedCollectionOnBase], [t0].[Id0], [t0].[Name0], [t0].[ParentCollectionId], [t0].[ParentReferenceId], [t0].[IsNestedCollectionDerived] +FROM [BaseEntities] AS [b] +LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d0] ON [b].[Id] = [d0].[DerivedInheritanceRelationshipEntityId] +LEFT JOIN ( + SELECT [b1].[Id], [b1].[BaseParentId], [b1].[Name], [d1].[DerivedProperty], CASE + WHEN [d1].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedCollectionOnBase], [t].[Id] AS [Id0], [t].[Name] AS [Name0], [t].[ParentCollectionId], [t].[ParentReferenceId], [t].[IsNestedCollectionDerived] + FROM [BaseCollectionsOnBase] AS [b1] + LEFT JOIN [DerivedCollectionsOnBase] AS [d1] ON [b1].[Id] = [d1].[Id] + LEFT JOIN ( + SELECT [n].[Id], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId], CASE + WHEN [n0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsNestedCollectionDerived] + FROM [NestedCollections] AS [n] + LEFT JOIN [NestedCollectionsDerived] AS [n0] ON [n].[Id] = [n0].[Id] + ) AS [t] ON [b1].[Id] = [t].[ParentCollectionId] +) AS [t0] ON [b].[Id] = [t0].[BaseParentId] +ORDER BY [b].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [t0].[Id], [t0].[Id0]"); + } + + public override void Nested_include_with_inheritance_collection_collection_reverse() + { + base.Nested_include_with_inheritance_collection_collection_reverse(); + + AssertSql( + @"SELECT [n].[Id], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId], CASE + WHEN [n0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsNestedCollectionDerived], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[DerivedProperty], [t].[IsDerivedCollectionOnBase], [t0].[Id], [t0].[Name], [t0].[BaseId], [t0].[IsDerivedInheritanceRelationshipEntity], [t0].[Id0], [t0].[OwnedReferenceOnBase_Id], [t0].[OwnedReferenceOnBase_Name], [t0].[Id1], [t0].[OwnedReferenceOnDerived_Id], [t0].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +FROM [NestedCollections] AS [n] +LEFT JOIN [NestedCollectionsDerived] AS [n0] ON [n].[Id] = [n0].[Id] +LEFT JOIN ( + SELECT [b].[Id], [b].[BaseParentId], [b].[Name], [d].[DerivedProperty], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedCollectionOnBase] + FROM [BaseCollectionsOnBase] AS [b] + LEFT JOIN [DerivedCollectionsOnBase] AS [d] ON [b].[Id] = [d].[Id] +) AS [t] ON [n].[ParentCollectionId] = [t].[Id] +LEFT JOIN ( + SELECT [b0].[Id], [b0].[Name], [d0].[BaseId], CASE + WHEN [d0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedInheritanceRelationshipEntity], [b0].[Id] AS [Id0], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [d0].[Id] AS [Id1], [d0].[OwnedReferenceOnDerived_Id], [d0].[OwnedReferenceOnDerived_Name] + FROM [BaseEntities] AS [b0] + LEFT JOIN [DerivedEntities] AS [d0] ON [b0].[Id] = [d0].[Id] +) AS [t0] ON [t].[BaseParentId] = [t0].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [t0].[Id] = [b1].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d1] ON [t0].[Id] = [d1].[DerivedInheritanceRelationshipEntityId] +ORDER BY [n].[Id], [t].[Id], [t0].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id]"); + } + + public override void Nested_include_with_inheritance_collection_reference() + { + base.Nested_include_with_inheritance_collection_reference(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsDerivedInheritanceRelationshipEntity], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [b0].[Name], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [d0].[Name], [t0].[Id], [t0].[BaseParentId], [t0].[Name], [t0].[DerivedProperty], [t0].[IsDerivedCollectionOnBase], [t0].[Id0], [t0].[Name0], [t0].[ParentCollectionId], [t0].[ParentReferenceId], [t0].[IsNestedReferenceDerived] +FROM [BaseEntities] AS [b] +LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b0] ON [b].[Id] = [b0].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d0] ON [b].[Id] = [d0].[DerivedInheritanceRelationshipEntityId] +LEFT JOIN ( + SELECT [b1].[Id], [b1].[BaseParentId], [b1].[Name], [d1].[DerivedProperty], CASE + WHEN [d1].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedCollectionOnBase], [t].[Id] AS [Id0], [t].[Name] AS [Name0], [t].[ParentCollectionId], [t].[ParentReferenceId], [t].[IsNestedReferenceDerived] + FROM [BaseCollectionsOnBase] AS [b1] + LEFT JOIN [DerivedCollectionsOnBase] AS [d1] ON [b1].[Id] = [d1].[Id] + LEFT JOIN ( + SELECT [n].[Id], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId], CASE + WHEN [n0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsNestedReferenceDerived] + FROM [NestedReferences] AS [n] + LEFT JOIN [NestedReferencesDerived] AS [n0] ON [n].[Id] = [n0].[Id] + ) AS [t] ON [b1].[Id] = [t].[ParentCollectionId] +) AS [t0] ON [b].[Id] = [t0].[BaseParentId] +ORDER BY [b].[Id], [b0].[BaseInheritanceRelationshipEntityId], [b0].[Id], [d0].[DerivedInheritanceRelationshipEntityId], [d0].[Id], [t0].[Id], [t0].[Id0]"); + } + + public override void Nested_include_with_inheritance_collection_reference_reverse() + { + base.Nested_include_with_inheritance_collection_reference_reverse(); + + AssertSql( + @"SELECT [n].[Id], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId], CASE + WHEN [n0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsNestedReferenceDerived], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[DerivedProperty], [t].[IsDerivedCollectionOnBase], [t0].[Id], [t0].[Name], [t0].[BaseId], [t0].[IsDerivedInheritanceRelationshipEntity], [t0].[Id0], [t0].[OwnedReferenceOnBase_Id], [t0].[OwnedReferenceOnBase_Name], [t0].[Id1], [t0].[OwnedReferenceOnDerived_Id], [t0].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +FROM [NestedReferences] AS [n] +LEFT JOIN [NestedReferencesDerived] AS [n0] ON [n].[Id] = [n0].[Id] +LEFT JOIN ( + SELECT [b].[Id], [b].[BaseParentId], [b].[Name], [d].[DerivedProperty], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedCollectionOnBase] + FROM [BaseCollectionsOnBase] AS [b] + LEFT JOIN [DerivedCollectionsOnBase] AS [d] ON [b].[Id] = [d].[Id] +) AS [t] ON [n].[ParentCollectionId] = [t].[Id] +LEFT JOIN ( + SELECT [b0].[Id], [b0].[Name], [d0].[BaseId], CASE + WHEN [d0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedInheritanceRelationshipEntity], [b0].[Id] AS [Id0], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [d0].[Id] AS [Id1], [d0].[OwnedReferenceOnDerived_Id], [d0].[OwnedReferenceOnDerived_Name] + FROM [BaseEntities] AS [b0] + LEFT JOIN [DerivedEntities] AS [d0] ON [b0].[Id] = [d0].[Id] +) AS [t0] ON [t].[BaseParentId] = [t0].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [t0].[Id] = [b1].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d1] ON [t0].[Id] = [d1].[DerivedInheritanceRelationshipEntityId] +ORDER BY [n].[Id], [t].[Id], [t0].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id]"); + } + + public override void Nested_include_with_inheritance_reference_collection() + { + base.Nested_include_with_inheritance_reference_collection(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsDerivedInheritanceRelationshipEntity], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[IsDerivedReferenceOnBase], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [t0].[Id], [t0].[Name], [t0].[ParentCollectionId], [t0].[ParentReferenceId], [t0].[IsNestedCollectionDerived] +FROM [BaseEntities] AS [b] +LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN ( + SELECT [b0].[Id], [b0].[BaseParentId], [b0].[Name], CASE + WHEN [d0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedReferenceOnBase] + FROM [BaseReferencesOnBase] AS [b0] + LEFT JOIN [DerivedReferencesOnBase] AS [d0] ON [b0].[Id] = [d0].[Id] +) AS [t] ON [b].[Id] = [t].[BaseParentId] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b].[Id] = [b1].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d1] ON [b].[Id] = [d1].[DerivedInheritanceRelationshipEntityId] +LEFT JOIN ( + SELECT [n].[Id], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId], CASE + WHEN [n0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsNestedCollectionDerived] + FROM [NestedCollections] AS [n] + LEFT JOIN [NestedCollectionsDerived] AS [n0] ON [n].[Id] = [n0].[Id] +) AS [t0] ON [t].[Id] = [t0].[ParentReferenceId] +ORDER BY [b].[Id], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [t0].[Id]"); + } + + public override void Nested_include_with_inheritance_reference_collection_on_base() + { + base.Nested_include_with_inheritance_reference_collection_on_base(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[IsDerivedReferenceOnBase], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name], [t0].[Id], [t0].[Name], [t0].[ParentCollectionId], [t0].[ParentReferenceId], [t0].[IsNestedCollectionDerived] +FROM [BaseEntities] AS [b] +INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN ( + SELECT [b0].[Id], [b0].[BaseParentId], [b0].[Name], CASE + WHEN [d0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedReferenceOnBase] + FROM [BaseReferencesOnBase] AS [b0] + LEFT JOIN [DerivedReferencesOnBase] AS [d0] ON [b0].[Id] = [d0].[Id] +) AS [t] ON [b].[Id] = [t].[BaseParentId] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b].[Id] = [b1].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d1] ON [b].[Id] = [d1].[DerivedInheritanceRelationshipEntityId] +LEFT JOIN ( + SELECT [n].[Id], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId], CASE + WHEN [n0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsNestedCollectionDerived] + FROM [NestedCollections] AS [n] + LEFT JOIN [NestedCollectionsDerived] AS [n0] ON [n].[Id] = [n0].[Id] +) AS [t0] ON [t].[Id] = [t0].[ParentReferenceId] +ORDER BY [b].[Id], [t].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [t0].[Id]"); + } + + public override void Nested_include_with_inheritance_reference_collection_reverse() + { + base.Nested_include_with_inheritance_reference_collection_reverse(); + + AssertSql( + @"SELECT [n].[Id], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId], CASE + WHEN [n0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsNestedCollectionDerived], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[IsDerivedReferenceOnBase], [t0].[Id], [t0].[Name], [t0].[BaseId], [t0].[IsDerivedInheritanceRelationshipEntity], [t0].[Id0], [t0].[OwnedReferenceOnBase_Id], [t0].[OwnedReferenceOnBase_Name], [t0].[Id1], [t0].[OwnedReferenceOnDerived_Id], [t0].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +FROM [NestedCollections] AS [n] +LEFT JOIN [NestedCollectionsDerived] AS [n0] ON [n].[Id] = [n0].[Id] +LEFT JOIN ( + SELECT [b].[Id], [b].[BaseParentId], [b].[Name], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedReferenceOnBase] + FROM [BaseReferencesOnBase] AS [b] + LEFT JOIN [DerivedReferencesOnBase] AS [d] ON [b].[Id] = [d].[Id] +) AS [t] ON [n].[ParentReferenceId] = [t].[Id] +LEFT JOIN ( + SELECT [b0].[Id], [b0].[Name], [d0].[BaseId], CASE + WHEN [d0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedInheritanceRelationshipEntity], [b0].[Id] AS [Id0], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [d0].[Id] AS [Id1], [d0].[OwnedReferenceOnDerived_Id], [d0].[OwnedReferenceOnDerived_Name] + FROM [BaseEntities] AS [b0] + LEFT JOIN [DerivedEntities] AS [d0] ON [b0].[Id] = [d0].[Id] +) AS [t0] ON [t].[BaseParentId] = [t0].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [t0].[Id] = [b1].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d1] ON [t0].[Id] = [d1].[DerivedInheritanceRelationshipEntityId] +ORDER BY [n].[Id], [t].[Id], [t0].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id]"); + } + + public override void Nested_include_with_inheritance_reference_reference() + { + base.Nested_include_with_inheritance_reference_reference(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsDerivedInheritanceRelationshipEntity], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[IsDerivedReferenceOnBase], [t0].[Id], [t0].[Name], [t0].[ParentCollectionId], [t0].[ParentReferenceId], [t0].[IsNestedReferenceDerived], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +FROM [BaseEntities] AS [b] +LEFT JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN ( + SELECT [b0].[Id], [b0].[BaseParentId], [b0].[Name], CASE + WHEN [d0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedReferenceOnBase] + FROM [BaseReferencesOnBase] AS [b0] + LEFT JOIN [DerivedReferencesOnBase] AS [d0] ON [b0].[Id] = [d0].[Id] +) AS [t] ON [b].[Id] = [t].[BaseParentId] +LEFT JOIN ( + SELECT [n].[Id], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId], CASE + WHEN [n0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsNestedReferenceDerived] + FROM [NestedReferences] AS [n] + LEFT JOIN [NestedReferencesDerived] AS [n0] ON [n].[Id] = [n0].[Id] +) AS [t0] ON [t].[Id] = [t0].[ParentReferenceId] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b].[Id] = [b1].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d1] ON [b].[Id] = [d1].[DerivedInheritanceRelationshipEntityId] +ORDER BY [b].[Id], [t].[Id], [t0].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id]"); + } + + public override void Nested_include_with_inheritance_reference_reference_on_base() + { + base.Nested_include_with_inheritance_reference_reference_on_base(); + + AssertSql( + @"SELECT [b].[Id], [b].[Name], [d].[BaseId], [b].[OwnedReferenceOnBase_Id], [b].[OwnedReferenceOnBase_Name], [d].[Id], [d].[OwnedReferenceOnDerived_Id], [d].[OwnedReferenceOnDerived_Name], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[IsDerivedReferenceOnBase], [t0].[Id], [t0].[Name], [t0].[ParentCollectionId], [t0].[ParentReferenceId], [t0].[IsNestedReferenceDerived], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +FROM [BaseEntities] AS [b] +INNER JOIN [DerivedEntities] AS [d] ON [b].[Id] = [d].[Id] +LEFT JOIN ( + SELECT [b0].[Id], [b0].[BaseParentId], [b0].[Name], CASE + WHEN [d0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedReferenceOnBase] + FROM [BaseReferencesOnBase] AS [b0] + LEFT JOIN [DerivedReferencesOnBase] AS [d0] ON [b0].[Id] = [d0].[Id] +) AS [t] ON [b].[Id] = [t].[BaseParentId] +LEFT JOIN ( + SELECT [n].[Id], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId], CASE + WHEN [n0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsNestedReferenceDerived] + FROM [NestedReferences] AS [n] + LEFT JOIN [NestedReferencesDerived] AS [n0] ON [n].[Id] = [n0].[Id] +) AS [t0] ON [t].[Id] = [t0].[ParentReferenceId] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [b].[Id] = [b1].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d1] ON [b].[Id] = [d1].[DerivedInheritanceRelationshipEntityId] +ORDER BY [b].[Id], [t].[Id], [t0].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id]"); + } + + public override void Nested_include_with_inheritance_reference_reference_reverse() + { + base.Nested_include_with_inheritance_reference_reference_reverse(); + + AssertSql( + @"SELECT [n].[Id], [n].[Name], [n].[ParentCollectionId], [n].[ParentReferenceId], CASE + WHEN [n0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) +END AS [IsNestedReferenceDerived], [t].[Id], [t].[BaseParentId], [t].[Name], [t].[IsDerivedReferenceOnBase], [t0].[Id], [t0].[Name], [t0].[BaseId], [t0].[IsDerivedInheritanceRelationshipEntity], [t0].[Id0], [t0].[OwnedReferenceOnBase_Id], [t0].[OwnedReferenceOnBase_Name], [t0].[Id1], [t0].[OwnedReferenceOnDerived_Id], [t0].[OwnedReferenceOnDerived_Name], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [b1].[Name], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id], [d1].[Name] +FROM [NestedReferences] AS [n] +LEFT JOIN [NestedReferencesDerived] AS [n0] ON [n].[Id] = [n0].[Id] +LEFT JOIN ( + SELECT [b].[Id], [b].[BaseParentId], [b].[Name], CASE + WHEN [d].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedReferenceOnBase] + FROM [BaseReferencesOnBase] AS [b] + LEFT JOIN [DerivedReferencesOnBase] AS [d] ON [b].[Id] = [d].[Id] +) AS [t] ON [n].[ParentReferenceId] = [t].[Id] +LEFT JOIN ( + SELECT [b0].[Id], [b0].[Name], [d0].[BaseId], CASE + WHEN [d0].[Id] IS NOT NULL THEN CAST(1 AS bit) + ELSE CAST(0 AS bit) + END AS [IsDerivedInheritanceRelationshipEntity], [b0].[Id] AS [Id0], [b0].[OwnedReferenceOnBase_Id], [b0].[OwnedReferenceOnBase_Name], [d0].[Id] AS [Id1], [d0].[OwnedReferenceOnDerived_Id], [d0].[OwnedReferenceOnDerived_Name] + FROM [BaseEntities] AS [b0] + LEFT JOIN [DerivedEntities] AS [d0] ON [b0].[Id] = [d0].[Id] +) AS [t0] ON [t].[BaseParentId] = [t0].[Id] +LEFT JOIN [BaseEntities_OwnedCollectionOnBase] AS [b1] ON [t0].[Id] = [b1].[BaseInheritanceRelationshipEntityId] +LEFT JOIN [DerivedEntities_OwnedCollectionOnDerived] AS [d1] ON [t0].[Id] = [d1].[DerivedInheritanceRelationshipEntityId] +ORDER BY [n].[Id], [t].[Id], [t0].[Id], [b1].[BaseInheritanceRelationshipEntityId], [b1].[Id], [d1].[DerivedInheritanceRelationshipEntityId], [d1].[Id]"); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/UdfDbFunctionSqlServerTests.cs b/test/EFCore.SqlServer.FunctionalTests/Query/UdfDbFunctionSqlServerTests.cs index c3cf4752b2a..44601b32cf4 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/UdfDbFunctionSqlServerTests.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/UdfDbFunctionSqlServerTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.EntityFrameworkCore.TestUtilities; @@ -742,10 +742,11 @@ public override void QF_Correlated_Func_Call_With_Navigation() { base.QF_Correlated_Func_Call_With_Navigation(); - AssertSql(@"SELECT [c].[Id], [t].[LastName], [t].[OrderId], [t].[Id] + AssertSql( + @"SELECT [c].[Id], [t].[CustomerName], [t].[OrderId], [t].[Id] FROM [Customers] AS [c] OUTER APPLY ( - SELECT [c0].[LastName], [m].[OrderId], [c0].[Id] + SELECT [c0].[LastName] AS [CustomerName], [m].[OrderId], [c0].[Id] FROM [dbo].[GetOrdersWithMultipleProducts]([c].[Id]) AS [m] INNER JOIN [Customers] AS [c0] ON [m].[CustomerId] = [c0].[Id] ) AS [t]