diff --git a/src/EFCore.Cosmos/Properties/CosmosStrings.Designer.cs b/src/EFCore.Cosmos/Properties/CosmosStrings.Designer.cs index cec48ff1591..1ff495217f8 100644 --- a/src/EFCore.Cosmos/Properties/CosmosStrings.Designer.cs +++ b/src/EFCore.Cosmos/Properties/CosmosStrings.Designer.cs @@ -220,6 +220,14 @@ public static string JsonPropertyCollision([CanBeNull] object property1, [CanBeN public static string ConnectionStringConflictingConfiguration => GetString("ConnectionStringConflictingConfiguration"); + /// + /// 'UpdateEntityType' called with '{derivedType}' which is not derived type of '{entityType}'. + /// + public static string InvalidDerivedTypeInEntityProjection([CanBeNull] object derivedType, [CanBeNull] object entityType) + => string.Format( + GetString("InvalidDerivedTypeInEntityProjection", nameof(derivedType), nameof(entityType)), + derivedType, entityType); + private static string GetString(string name, params string[] formatterNames) { var value = _resourceManager.GetString(name); diff --git a/src/EFCore.Cosmos/Properties/CosmosStrings.resx b/src/EFCore.Cosmos/Properties/CosmosStrings.resx index 5ee4d3999f9..fc461a4072a 100644 --- a/src/EFCore.Cosmos/Properties/CosmosStrings.resx +++ b/src/EFCore.Cosmos/Properties/CosmosStrings.resx @@ -198,4 +198,7 @@ Both the connection string and account key or account endpoint were specified. Only specify one set of connection details. + + 'UpdateEntityType' called with '{derivedType}' which is not derived type of '{entityType}'. + \ No newline at end of file diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs index c7b6445882e..24ad6b812b4 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs @@ -711,6 +711,53 @@ protected override ShapedQueryExpression TranslateOfType(ShapedQueryExpression s Check.NotNull(source, nameof(source)); Check.NotNull(resultType, nameof(resultType)); + if (source.ShaperExpression is EntityShaperExpression entityShaperExpression) + { + var entityType = entityShaperExpression.EntityType; + if (entityType.ClrType == resultType) + { + return source; + } + + var parameterExpression = Expression.Parameter(entityShaperExpression.Type); + var predicate = Expression.Lambda(Expression.TypeIs(parameterExpression, resultType), parameterExpression); + var translation = TranslateLambdaExpression(source, predicate); + if (translation == null) + { + // EntityType is not part of hierarchy + return null; + } + + var selectExpression = (SelectExpression)source.QueryExpression; + if (!(translation is SqlConstantExpression sqlConstantExpression + && sqlConstantExpression.Value is bool constantValue + && constantValue)) + { + selectExpression.ApplyPredicate(translation); + } + + var baseType = entityType.GetAllBaseTypes().SingleOrDefault(et => et.ClrType == resultType); + if (baseType != null) + { + return source.UpdateShaperExpression(entityShaperExpression.WithEntityType(baseType)); + } + + var derivedType = entityType.GetDerivedTypes().Single(et => et.ClrType == resultType); + 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(projectionMember); + selectExpression.ReplaceProjectionMapping( + new Dictionary + { + { projectionMember, entityProjectionExpression.UpdateEntityType(derivedType) } + }); + + return source.UpdateShaperExpression(entityShaperExpression.WithEntityType(derivedType)); + } + return null; } diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.cs index b54035684e9..1ca05f0a247 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosSqlTranslatingExpressionVisitor.cs @@ -598,6 +598,43 @@ protected override Expression VisitUnary(UnaryExpression unaryExpression) return null; } + /// + protected override Expression VisitTypeBinary(TypeBinaryExpression typeBinaryExpression) + { + Check.NotNull(typeBinaryExpression, nameof(typeBinaryExpression)); + + var innerExpression = Visit(typeBinaryExpression.Expression); + + if (typeBinaryExpression.NodeType == ExpressionType.TypeIs + && innerExpression is EntityReferenceExpression entityReferenceExpression) + { + var entityType = entityReferenceExpression.EntityType; + if (entityType.GetAllBaseTypesInclusive().Any(et => et.ClrType == typeBinaryExpression.TypeOperand)) + { + return _sqlExpressionFactory.Constant(true); + } + + var derivedType = entityType.GetDerivedTypes().SingleOrDefault(et => et.ClrType == typeBinaryExpression.TypeOperand); + if (derivedType != null + && TryBindMember(entityReferenceExpression, + MemberIdentity.Create(entityType.GetDiscriminatorProperty().Name)) is SqlExpression discriminatorColumn) + { + var concreteEntityTypes = derivedType.GetConcreteDerivedTypesInclusive().ToList(); + + return concreteEntityTypes.Count == 1 + ? _sqlExpressionFactory.Equal( + discriminatorColumn, + _sqlExpressionFactory.Constant(concreteEntityTypes[0].GetDiscriminatorValue())) + : (SqlExpression)_sqlExpressionFactory.In( + discriminatorColumn, + _sqlExpressionFactory.Constant(concreteEntityTypes.Select(et => et.GetDiscriminatorValue()).ToList()), + negated: false); + } + } + + return null; + } + private Expression TryBindMember(Expression source, MemberIdentity member) { if (!(source is EntityReferenceExpression entityReferenceExpression)) diff --git a/src/EFCore.Cosmos/Query/Internal/EntityProjectionExpression.cs b/src/EFCore.Cosmos/Query/Internal/EntityProjectionExpression.cs index 8f8aa3bcc11..d92b3cc7575 100644 --- a/src/EFCore.Cosmos/Query/Internal/EntityProjectionExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/EntityProjectionExpression.cs @@ -7,6 +7,7 @@ using System.Linq.Expressions; using System.Reflection; using JetBrains.Annotations; +using Microsoft.EntityFrameworkCore.Cosmos.Internal; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; @@ -22,10 +23,10 @@ namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal /// public class EntityProjectionExpression : Expression, IPrintableExpression, IAccessExpression { - private readonly IDictionary _propertyExpressionsCache + private readonly IDictionary _propertyExpressionsMap = new Dictionary(); - private readonly IDictionary _navigationExpressionsCache + private readonly IDictionary _navigationExpressionsMap = new Dictionary(); /// @@ -121,10 +122,10 @@ public virtual Expression BindProperty([NotNull] IProperty property, bool client "GetProperty", nameof(IProperty), EntityType.DisplayName(), $"Property:{property.Name}")); } - if (!_propertyExpressionsCache.TryGetValue(property, out var expression)) + if (!_propertyExpressionsMap.TryGetValue(property, out var expression)) { expression = new KeyAccessExpression(property, AccessExpression); - _propertyExpressionsCache[property] = expression; + _propertyExpressionsMap[property] = expression; } if (!clientEval @@ -153,20 +154,15 @@ public virtual Expression BindNavigation([NotNull] INavigation navigation, bool "GetNavigation", nameof(INavigation), EntityType.DisplayName(), $"Navigation:{navigation.Name}")); } - if (!_navigationExpressionsCache.TryGetValue(navigation, out var expression)) + if (!_navigationExpressionsMap.TryGetValue(navigation, out var expression)) { - if (navigation.IsCollection) - { - expression = new ObjectArrayProjectionExpression(navigation, AccessExpression); - } - else - { - expression = new EntityProjectionExpression( + expression = navigation.IsCollection + ? new ObjectArrayProjectionExpression(navigation, AccessExpression) + : (IAccessExpression)new EntityProjectionExpression( navigation.TargetEntityType, new ObjectAccessExpression(navigation, AccessExpression)); - } - _navigationExpressionsCache[navigation] = expression; + _navigationExpressionsMap[navigation] = expression; } if (!clientEval @@ -231,6 +227,25 @@ private Expression BindMember(MemberIdentity member, Type entityClrType, bool cl return null; } + /// + /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to + /// the same compatibility standards as public APIs. It may be changed or removed without notice in + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + public virtual EntityProjectionExpression UpdateEntityType([NotNull] IEntityType derivedType) + { + Check.NotNull(derivedType, nameof(derivedType)); + + if (!derivedType.GetAllBaseTypes().Contains(EntityType)) + { + throw new InvalidOperationException(CosmosStrings.InvalidDerivedTypeInEntityProjection( + derivedType.DisplayName(), EntityType.DisplayName())); + } + + return new EntityProjectionExpression(derivedType, AccessExpression); + } + /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in diff --git a/src/EFCore.InMemory/Properties/InMemoryStrings.Designer.cs b/src/EFCore.InMemory/Properties/InMemoryStrings.Designer.cs index 6342d9e0340..475eba63eda 100644 --- a/src/EFCore.InMemory/Properties/InMemoryStrings.Designer.cs +++ b/src/EFCore.InMemory/Properties/InMemoryStrings.Designer.cs @@ -1,4 +1,4 @@ -// +// using System; using System.Reflection; @@ -63,6 +63,14 @@ public static string InvalidStateEncountered([CanBeNull] object state) public static string DefaultIfEmptyAppliedAfterProjection => GetString("DefaultIfEmptyAppliedAfterProjection"); + /// + /// 'UpdateEntityType' called with '{derivedType}' which is not derived type of '{entityType}'. + /// + public static string InvalidDerivedTypeInEntityProjection([CanBeNull] object derivedType, [CanBeNull] object entityType) + => string.Format( + GetString("InvalidDerivedTypeInEntityProjection", nameof(derivedType), nameof(entityType)), + derivedType, entityType); + private static string GetString(string name, params string[] formatterNames) { var value = _resourceManager.GetString(name); diff --git a/src/EFCore.InMemory/Properties/InMemoryStrings.resx b/src/EFCore.InMemory/Properties/InMemoryStrings.resx index e585c3ae4b9..9d5449aeb74 100644 --- a/src/EFCore.InMemory/Properties/InMemoryStrings.resx +++ b/src/EFCore.InMemory/Properties/InMemoryStrings.resx @@ -1,17 +1,17 @@  - @@ -143,4 +143,7 @@ Cannot apply DefaultIfEmpty after a client-evaluated projection. + + 'UpdateEntityType' called with '{derivedType}' which is not derived type of '{entityType}'. + \ No newline at end of file diff --git a/src/EFCore.InMemory/Query/Internal/EntityProjectionExpression.cs b/src/EFCore.InMemory/Query/Internal/EntityProjectionExpression.cs index b32359725cb..52238863dd1 100644 --- a/src/EFCore.InMemory/Query/Internal/EntityProjectionExpression.cs +++ b/src/EFCore.InMemory/Query/Internal/EntityProjectionExpression.cs @@ -3,9 +3,11 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Linq.Expressions; using JetBrains.Annotations; using Microsoft.EntityFrameworkCore.Diagnostics; +using Microsoft.EntityFrameworkCore.InMemory.Internal; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Query; using Microsoft.EntityFrameworkCore.Utilities; @@ -68,6 +70,12 @@ public EntityProjectionExpression( /// public virtual EntityProjectionExpression UpdateEntityType([NotNull] IEntityType derivedType) { + if (!derivedType.GetAllBaseTypes().Contains(EntityType)) + { + throw new InvalidOperationException(InMemoryStrings.InvalidDerivedTypeInEntityProjection( + derivedType.DisplayName(), EntityType.DisplayName())); + } + var readExpressionMap = new Dictionary(); foreach (var kvp in _readExpressionMap) { diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs index 77162079348..7df03ed425a 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryExpressionTranslatingExpressionVisitor.cs @@ -808,7 +808,7 @@ protected override Expression VisitTypeBinary(TypeBinaryExpression typeBinaryExp } } - return Expression.Constant(false); + return null; } /// diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs index 6bba55266e9..e09439cd014 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryQueryableMethodTranslatingExpressionVisitor.cs @@ -800,56 +800,36 @@ protected override ShapedQueryExpression TranslateOfType(ShapedQueryExpression s return source; } + var parameterExpression = Expression.Parameter(entityShaperExpression.Type); + var predicate = Expression.Lambda(Expression.TypeIs(parameterExpression, resultType), parameterExpression); + source = TranslateWhere(source, predicate); + if (source == null) + { + // EntityType is not part of hierarchy + return null; + } + var baseType = entityType.GetAllBaseTypes().SingleOrDefault(et => et.ClrType == resultType); if (baseType != null) { return source.UpdateShaperExpression(entityShaperExpression.WithEntityType(baseType)); } - var derivedType = entityType.GetDerivedTypes().SingleOrDefault(et => et.ClrType == resultType); - if (derivedType != null) - { - var inMemoryQueryExpression = (InMemoryQueryExpression)source.QueryExpression; - var discriminatorProperty = entityType.GetDiscriminatorProperty(); - var parameter = Expression.Parameter(entityType.ClrType); + var derivedType = entityType.GetDerivedTypes().Single(et => et.ClrType == resultType); + var inMemoryQueryExpression = (InMemoryQueryExpression)source.QueryExpression; - var equals = Expression.Equal( - parameter.CreateEFPropertyExpression(discriminatorProperty), - Expression.Constant(derivedType.GetDiscriminatorValue(), discriminatorProperty.ClrType)); + var projectionBindingExpression = (ProjectionBindingExpression)entityShaperExpression.ValueBufferExpression; + var projectionMember = projectionBindingExpression.ProjectionMember; + Check.DebugAssert(new ProjectionMember().Equals(projectionMember), "Invalid ProjectionMember when processing OfType"); - foreach (var derivedDerivedType in derivedType.GetDerivedTypes()) + var entityProjectionExpression = (EntityProjectionExpression)inMemoryQueryExpression.GetMappedProjection(projectionMember); + inMemoryQueryExpression.ReplaceProjectionMapping( + new Dictionary { - equals = Expression.OrElse( - equals, - Expression.Equal( - parameter.CreateEFPropertyExpression(discriminatorProperty), - Expression.Constant(derivedDerivedType.GetDiscriminatorValue(), discriminatorProperty.ClrType))); - } + { projectionMember, entityProjectionExpression.UpdateEntityType(derivedType) } + }); - var discriminatorPredicate = TranslateLambdaExpression(source, Expression.Lambda(equals, parameter)); - if (discriminatorPredicate == null) - { - return null; - } - - inMemoryQueryExpression.UpdateServerQueryExpression( - Expression.Call( - EnumerableMethods.Where.MakeGenericMethod(typeof(ValueBuffer)), - inMemoryQueryExpression.ServerQueryExpression, - discriminatorPredicate)); - - var projectionBindingExpression = (ProjectionBindingExpression)entityShaperExpression.ValueBufferExpression; - var projectionMember = projectionBindingExpression.ProjectionMember; - var entityProjection = (EntityProjectionExpression)inMemoryQueryExpression.GetMappedProjection(projectionMember); - - inMemoryQueryExpression.ReplaceProjectionMapping( - new Dictionary - { - { projectionMember, entityProjection.UpdateEntityType(derivedType) } - }); - - return source.UpdateShaperExpression(entityShaperExpression.WithEntityType(derivedType)); - } + return source.UpdateShaperExpression(entityShaperExpression.WithEntityType(derivedType)); } return null; diff --git a/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs b/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs index d9a5fc25ae8..cca2aac6c00 100644 --- a/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs +++ b/src/EFCore.Relational/Properties/RelationalStrings.Designer.cs @@ -1,4 +1,3 @@ - // using System; @@ -1032,6 +1031,14 @@ public static string CustomQueryMappingOnOwner public static string NullabilityInfoOnlyAllowedOnScalarFunctions => GetString("NullabilityInfoOnlyAllowedOnScalarFunctions"); + /// + /// 'UpdateEntityType' called with '{derivedType}' which is not derived type of '{entityType}'. + /// + public static string InvalidDerivedTypeInEntityProjection([CanBeNull] object derivedType, [CanBeNull] object entityType) + => string.Format( + GetString("InvalidDerivedTypeInEntityProjection", nameof(derivedType), nameof(entityType)), + derivedType, entityType); + private static string GetString(string name, params string[] formatterNames) { var value = _resourceManager.GetString(name); diff --git a/src/EFCore.Relational/Properties/RelationalStrings.resx b/src/EFCore.Relational/Properties/RelationalStrings.resx index 8f2e54bcdc5..dbd3530916e 100644 --- a/src/EFCore.Relational/Properties/RelationalStrings.resx +++ b/src/EFCore.Relational/Properties/RelationalStrings.resx @@ -732,4 +732,7 @@ Nullability information should only be specified for scalar database functions. + + 'UpdateEntityType' called with '{derivedType}' which is not derived type of '{entityType}'. + \ No newline at end of file diff --git a/src/EFCore.Relational/Query/EntityProjectionExpression.cs b/src/EFCore.Relational/Query/EntityProjectionExpression.cs index 39833c1d21a..d52eaec22ad 100644 --- a/src/EFCore.Relational/Query/EntityProjectionExpression.cs +++ b/src/EFCore.Relational/Query/EntityProjectionExpression.cs @@ -122,6 +122,12 @@ public virtual EntityProjectionExpression UpdateEntityType([NotNull] IEntityType { Check.NotNull(derivedType, nameof(derivedType)); + if (!derivedType.GetAllBaseTypes().Contains(EntityType)) + { + throw new InvalidOperationException(RelationalStrings.InvalidDerivedTypeInEntityProjection( + derivedType.DisplayName(), EntityType.DisplayName())); + } + var propertyExpressionMap = new Dictionary(); foreach (var kvp in _propertyExpressionMap) { diff --git a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs index 6baf1a7b41c..833e1957f55 100644 --- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs @@ -775,107 +775,46 @@ protected override ShapedQueryExpression TranslateOfType(ShapedQueryExpression s return source; } - var baseType = entityType.GetAllBaseTypes().SingleOrDefault(et => et.ClrType == resultType); - if (baseType != null) + var parameterExpression = Expression.Parameter(entityShaperExpression.Type); + var predicate = Expression.Lambda(Expression.TypeIs(parameterExpression, resultType), parameterExpression); + var translation = TranslateLambdaExpression(source, predicate); + if (translation == null) { - return source.UpdateShaperExpression(entityShaperExpression.WithEntityType(baseType)); + // EntityType is not part of hierarchy + return null; } - var derivedType = entityType.GetDerivedTypes().SingleOrDefault(et => et.ClrType == resultType); - if (derivedType != null) + var selectExpression = (SelectExpression)source.QueryExpression; + if (!(translation is SqlConstantExpression sqlConstantExpression + && sqlConstantExpression.Value is bool constantValue + && constantValue)) { - var discriminatorProperty = entityType.GetDiscriminatorProperty(); - if (discriminatorProperty == null) - { - var selectExpression = (SelectExpression)source.QueryExpression; - var discriminatorValues = derivedType.GetTptDiscriminatorValues(); - 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(projectionMember); + selectExpression.ApplyPredicate(translation); + } - var predicate = GeneratePredicateTPT(entityProjectionExpression); + var baseType = entityType.GetAllBaseTypes().SingleOrDefault(et => et.ClrType == resultType); + if (baseType != null) + { + return source.UpdateShaperExpression(entityShaperExpression.WithEntityType(baseType)); + } - selectExpression.ApplyPredicate(predicate); - selectExpression.ReplaceProjectionMapping( - new Dictionary - { - { projectionMember, entityProjectionExpression.UpdateEntityType(derivedType) } - }); + var derivedType = entityType.GetDerivedTypes().Single(et => et.ClrType == resultType); + var projectionBindingExpression = (ProjectionBindingExpression)entityShaperExpression.ValueBufferExpression; - SqlExpression GeneratePredicateTPT(EntityProjectionExpression entityProjectionExpression) - { - if (entityProjectionExpression.DiscriminatorExpression is CaseExpression caseExpression) - { - var matchingCaseWhenClauses = caseExpression.WhenClauses - .Where(wc => discriminatorValues.Contains((string)((SqlConstantExpression)wc.Result).Value)) - .ToList(); - - return matchingCaseWhenClauses.Count == 1 - ? matchingCaseWhenClauses[0].Test - : matchingCaseWhenClauses.Select(e => e.Test) - .Aggregate((l, r) => _sqlExpressionFactory.OrElse(l, r)); - } + var projectionMember = projectionBindingExpression.ProjectionMember; + Check.DebugAssert(new ProjectionMember().Equals(projectionMember), "Invalid ProjectionMember when processing OfType"); - return discriminatorValues.Count == 1 - ? _sqlExpressionFactory.Equal( - entityProjectionExpression.DiscriminatorExpression, - _sqlExpressionFactory.Constant(discriminatorValues[0])) - : (SqlExpression)_sqlExpressionFactory.In( - entityProjectionExpression.DiscriminatorExpression, - _sqlExpressionFactory.Constant(discriminatorValues), - negated: false); - } - } - else if (!derivedType.GetRootType().GetIsDiscriminatorMappingComplete() - || !derivedType.GetAllBaseTypesInclusiveAscending() - .All(e => (e == derivedType || e.IsAbstract()) && !HasSiblings(e))) + var entityProjectionExpression = (EntityProjectionExpression)selectExpression.GetMappedProjection(projectionMember); + selectExpression.ReplaceProjectionMapping( + new Dictionary { - 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(projectionMember); - var discriminatorColumn = entityProjectionExpression.BindProperty(discriminatorProperty); - - var predicate = concreteEntityTypes.Count == 1 - ? _sqlExpressionFactory.Equal( - discriminatorColumn, - _sqlExpressionFactory.Constant(concreteEntityTypes[0].GetDiscriminatorValue())) - : (SqlExpression)_sqlExpressionFactory.In( - discriminatorColumn, - _sqlExpressionFactory.Constant(concreteEntityTypes.Select(et => et.GetDiscriminatorValue())), - negated: false); - - selectExpression.ApplyPredicate(predicate); - selectExpression.ReplaceProjectionMapping( - new Dictionary - { - { projectionMember, entityProjectionExpression.UpdateEntityType(derivedType) } - }); - } - - return source.UpdateShaperExpression(entityShaperExpression.WithEntityType(derivedType)); - } + { projectionMember, entityProjectionExpression.UpdateEntityType(derivedType) } + }); - // If the resultType is not part of hierarchy then we don't know how to materialize. + return source.UpdateShaperExpression(entityShaperExpression.WithEntityType(derivedType)); } return null; - - bool HasSiblings(IEntityType entityType) - { - return entityType.BaseType?.GetDirectlyDerivedTypes().Any(i => i != entityType) == true; - } } /// diff --git a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs index c0128ba7575..d9c8a5daa9f 100644 --- a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs @@ -838,24 +838,36 @@ SqlExpression GeneratePredicateTPT(EntityProjectionExpression entityProjectionEx } else { - var concreteEntityTypes = derivedType.GetConcreteDerivedTypesInclusive().ToList(); - var discriminatorColumn = BindProperty(entityReferenceExpression, discriminatorProperty); - if (discriminatorColumn != null) + if (!derivedType.GetRootType().GetIsDiscriminatorMappingComplete() + || !derivedType.GetAllBaseTypesInclusiveAscending() + .All(e => (e == derivedType || e.IsAbstract()) && !HasSiblings(e))) { - return concreteEntityTypes.Count == 1 - ? _sqlExpressionFactory.Equal( - discriminatorColumn, - _sqlExpressionFactory.Constant(concreteEntityTypes[0].GetDiscriminatorValue())) - : (Expression)_sqlExpressionFactory.In( - discriminatorColumn, - _sqlExpressionFactory.Constant(concreteEntityTypes.Select(et => et.GetDiscriminatorValue()).ToList()), - negated: false); + var concreteEntityTypes = derivedType.GetConcreteDerivedTypesInclusive().ToList(); + var discriminatorColumn = BindProperty(entityReferenceExpression, discriminatorProperty); + if (discriminatorColumn != null) + { + return concreteEntityTypes.Count == 1 + ? _sqlExpressionFactory.Equal( + discriminatorColumn, + _sqlExpressionFactory.Constant(concreteEntityTypes[0].GetDiscriminatorValue())) + : (Expression)_sqlExpressionFactory.In( + discriminatorColumn, + _sqlExpressionFactory.Constant(concreteEntityTypes.Select(et => et.GetDiscriminatorValue()).ToList()), + negated: false); + } + } + else + { + return _sqlExpressionFactory.Constant(true); } } } } return null; + + static bool HasSiblings(IEntityType entityType) + => entityType.BaseType?.GetDirectlyDerivedTypes().Any(i => i != entityType) == true; } /// diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/InheritanceQueryCosmosFixture.cs b/test/EFCore.Cosmos.FunctionalTests/Query/InheritanceQueryCosmosFixture.cs new file mode 100644 index 00000000000..40b4713c1e7 --- /dev/null +++ b/test/EFCore.Cosmos.FunctionalTests/Query/InheritanceQueryCosmosFixture.cs @@ -0,0 +1,17 @@ +// 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; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; + +namespace Microsoft.EntityFrameworkCore.Query +{ + public class InheritanceQueryCosmosFixture : InheritanceQueryFixtureBase + { + protected override ITestStoreFactory TestStoreFactory => CosmosTestStoreFactory.Instance; + + public TestSqlLoggerFactory TestSqlLoggerFactory + => (TestSqlLoggerFactory)ServiceProvider.GetRequiredService(); + } +} diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/InheritanceQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/InheritanceQueryCosmosTest.cs new file mode 100644 index 00000000000..868923500a3 --- /dev/null +++ b/test/EFCore.Cosmos.FunctionalTests/Query/InheritanceQueryCosmosTest.cs @@ -0,0 +1,419 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System.Threading.Tasks; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.EntityFrameworkCore.Query +{ + public class InheritanceQueryCosmosTest : InheritanceQueryTestBase + { + public InheritanceQueryCosmosTest(InheritanceQueryCosmosFixture fixture, ITestOutputHelper testOutputHelper) + : base(fixture) + { + ClearLog(); + //TestLoggerFactory.TestOutputHelper = testOutputHelper; + } + + public override async Task Can_query_when_shared_column(bool async) + { + await base.Can_query_when_shared_column(async); + + AssertSql( + @"SELECT c +FROM root c +WHERE (c[""Discriminator""] = ""Coke"") +OFFSET 0 LIMIT 2", + // + @"SELECT c +FROM root c +WHERE (c[""Discriminator""] = ""Lilt"") +OFFSET 0 LIMIT 2", + // + @"SELECT c +FROM root c +WHERE (c[""Discriminator""] = ""Tea"") +OFFSET 0 LIMIT 2"); + } + + public override async Task Can_query_all_types_when_shared_column(bool async) + { + await base.Can_query_all_types_when_shared_column(async); + + AssertSql( + @"SELECT c +FROM root c +WHERE c[""Discriminator""] IN (""Drink"", ""Coke"", ""Lilt"", ""Tea"")"); + } + + public override async Task Can_use_of_type_animal(bool async) + { + await base.Can_use_of_type_animal(async); + + AssertSql( + @"SELECT c +FROM root c +WHERE c[""Discriminator""] IN (""Eagle"", ""Kiwi"") +ORDER BY c[""Species""]"); + } + + public override async Task Can_use_is_kiwi(bool async) + { + await base.Can_use_is_kiwi(async); + + AssertSql( + @"SELECT c +FROM root c +WHERE (c[""Discriminator""] IN (""Eagle"", ""Kiwi"") AND (c[""Discriminator""] = ""Kiwi""))"); + } + + public override async Task Can_use_backwards_is_animal(bool async) + { + await base.Can_use_backwards_is_animal(async); + + AssertSql( + @"SELECT c +FROM root c +WHERE (c[""Discriminator""] = ""Kiwi"")"); + } + + public override async Task Can_use_is_kiwi_with_other_predicate(bool async) + { + await base.Can_use_is_kiwi_with_other_predicate(async); + + AssertSql( + @"SELECT c +FROM root c +WHERE (c[""Discriminator""] IN (""Eagle"", ""Kiwi"") AND ((c[""Discriminator""] = ""Kiwi"") AND (c[""CountryId""] = 1)))"); + } + + public override async Task Can_use_is_kiwi_in_projection(bool async) + { + await base.Can_use_is_kiwi_in_projection(async); + + AssertSql( + @"SELECT VALUE {""c"" : (c[""Discriminator""] = ""Kiwi"")} +FROM root c +WHERE c[""Discriminator""] IN (""Eagle"", ""Kiwi"")"); + } + + public override async Task Can_use_of_type_bird(bool async) + { + await base.Can_use_of_type_bird(async); + + AssertSql( + @"SELECT c +FROM root c +WHERE (c[""Discriminator""] IN (""Eagle"", ""Kiwi"") AND c[""Discriminator""] IN (""Eagle"", ""Kiwi"")) +ORDER BY c[""Species""]"); + } + + public override async Task Can_use_of_type_bird_predicate(bool async) + { + await base.Can_use_of_type_bird_predicate(async); + + AssertSql( + @"SELECT c +FROM root c +WHERE ((c[""Discriminator""] IN (""Eagle"", ""Kiwi"") AND (c[""CountryId""] = 1)) AND c[""Discriminator""] IN (""Eagle"", ""Kiwi"")) +ORDER BY c[""Species""]"); + } + + public override async Task Can_use_of_type_bird_with_projection(bool async) + { + await base.Can_use_of_type_bird_with_projection(async); + + AssertSql( + @"SELECT c[""EagleId""] +FROM root c +WHERE (c[""Discriminator""] IN (""Eagle"", ""Kiwi"") AND c[""Discriminator""] IN (""Eagle"", ""Kiwi""))"); + } + + public override async Task Can_use_of_type_bird_first(bool async) + { + await base.Can_use_of_type_bird_first(async); + + AssertSql( + @"SELECT c +FROM root c +WHERE (c[""Discriminator""] IN (""Eagle"", ""Kiwi"") AND c[""Discriminator""] IN (""Eagle"", ""Kiwi"")) +ORDER BY c[""Species""] +OFFSET 0 LIMIT 1"); + } + + public override async Task Can_use_of_type_kiwi(bool async) + { + await base.Can_use_of_type_kiwi(async); + + AssertSql( + @"SELECT c +FROM root c +WHERE (c[""Discriminator""] IN (""Eagle"", ""Kiwi"") AND (c[""Discriminator""] = ""Kiwi""))"); + } + + public override async Task Can_use_backwards_of_type_animal(bool async) + { + await base.Can_use_backwards_of_type_animal(async); + + AssertSql(" "); + } + + public override async Task Can_use_of_type_rose(bool async) + { + await base.Can_use_of_type_rose(async); + + AssertSql( + @"SELECT c +FROM root c +WHERE (c[""Discriminator""] IN (""Daisy"", ""Rose"") AND (c[""Discriminator""] = ""Rose""))"); + } + + public override async Task Can_query_all_animals(bool async) + { + await base.Can_query_all_animals(async); + + AssertSql( + @"SELECT c +FROM root c +WHERE c[""Discriminator""] IN (""Eagle"", ""Kiwi"") +ORDER BY c[""Species""]"); + } + + [ConditionalTheory(Skip = "Issue#17246 Views are not supported")] + public override async Task Can_query_all_animal_views(bool async) + { + await base.Can_query_all_animal_views(async); + + AssertSql(" "); + } + + public override async Task Can_query_all_plants(bool async) + { + await base.Can_query_all_plants(async); + + AssertSql( + @"SELECT c +FROM root c +WHERE c[""Discriminator""] IN (""Daisy"", ""Rose"") +ORDER BY c[""Species""]"); + } + + public override async Task Can_filter_all_animals(bool async) + { + await base.Can_filter_all_animals(async); + + AssertSql( + @"SELECT c +FROM root c +WHERE (c[""Discriminator""] IN (""Eagle"", ""Kiwi"") AND (c[""Name""] = ""Great spotted kiwi"")) +ORDER BY c[""Species""]"); + } + + public override async Task Can_query_all_birds(bool async) + { + await base.Can_query_all_birds(async); + + AssertSql( + @"SELECT c +FROM root c +WHERE c[""Discriminator""] IN (""Eagle"", ""Kiwi"") +ORDER BY c[""Species""]"); + } + + public override async Task Can_query_just_kiwis(bool async) + { + await base.Can_query_just_kiwis(async); + + AssertSql( + @"SELECT c +FROM root c +WHERE (c[""Discriminator""] = ""Kiwi"") +OFFSET 0 LIMIT 2"); + } + + public override async Task Can_query_just_roses(bool async) + { + await base.Can_query_just_roses(async); + + AssertSql( + @"SELECT c +FROM root c +WHERE (c[""Discriminator""] = ""Rose"") +OFFSET 0 LIMIT 2"); + } + + [ConditionalTheory(Skip = "Issue#17246 Non-embedded Include")] + public override async Task Can_include_animals(bool async) + { + await base.Can_include_animals(async); + + AssertSql(" "); + } + + [ConditionalTheory(Skip = "Issue#17246 Non-embedded Include")] + public override async Task Can_include_prey(bool async) + { + await base.Can_include_prey(async); + + AssertSql(" "); + } + + public override async Task Can_use_of_type_kiwi_where_south_on_derived_property(bool async) + { + await base.Can_use_of_type_kiwi_where_south_on_derived_property(async); + + AssertSql( + @"SELECT c +FROM root c +WHERE ((c[""Discriminator""] IN (""Eagle"", ""Kiwi"") AND (c[""Discriminator""] = ""Kiwi"")) AND (c[""FoundOn""] = 1))"); + } + + public override async Task Can_use_of_type_kiwi_where_north_on_derived_property(bool async) + { + await base.Can_use_of_type_kiwi_where_north_on_derived_property(async); + + AssertSql( + @"SELECT c +FROM root c +WHERE ((c[""Discriminator""] IN (""Eagle"", ""Kiwi"") AND (c[""Discriminator""] = ""Kiwi"")) AND (c[""FoundOn""] = 0))"); + } + + public override async Task Discriminator_used_when_projection_over_derived_type(bool async) + { + await base.Discriminator_used_when_projection_over_derived_type(async); + + AssertSql( + @"SELECT c[""FoundOn""] +FROM root c +WHERE (c[""Discriminator""] = ""Kiwi"")"); + } + + public override async Task Discriminator_used_when_projection_over_derived_type2(bool async) + { + await base.Discriminator_used_when_projection_over_derived_type2(async); + + AssertSql( + @"SELECT c[""IsFlightless""], c[""Discriminator""] +FROM root c +WHERE c[""Discriminator""] IN (""Eagle"", ""Kiwi"")"); + } + + public override async Task Discriminator_with_cast_in_shadow_property(bool async) + { + await base.Discriminator_with_cast_in_shadow_property(async); + + AssertSql( + @"SELECT VALUE {""Predator"" : c[""EagleId""]} +FROM root c +WHERE (c[""Discriminator""] IN (""Eagle"", ""Kiwi"") AND (""Kiwi"" = c[""Discriminator""]))"); + } + + public override async Task Discriminator_used_when_projection_over_of_type(bool async) + { + await base.Discriminator_used_when_projection_over_of_type(async); + + AssertSql( + @"SELECT c[""FoundOn""] +FROM root c +WHERE (c[""Discriminator""] IN (""Eagle"", ""Kiwi"") AND (c[""Discriminator""] = ""Kiwi""))"); + } + + [ConditionalFact(Skip = "Issue#17246 Transations not supported")] + public override void Can_insert_update_delete() + { + base.Can_insert_update_delete(); + + AssertSql(" "); + } + + public override async Task Union_siblings_with_duplicate_property_in_subquery(bool async) + { + await base.Union_siblings_with_duplicate_property_in_subquery(async); + + AssertSql(" "); + } + + public override async Task OfType_Union_subquery(bool async) + { + await base.OfType_Union_subquery(async); + + AssertSql(" "); + } + + public override async Task OfType_Union_OfType(bool async) + { + await base.OfType_Union_OfType(async); + + AssertSql(" "); + } + + public override async Task Subquery_OfType(bool async) + { + await base.Subquery_OfType(async); + + AssertSql( + @"@__p_0='5' + +SELECT DISTINCT c +FROM root c +WHERE (c[""Discriminator""] IN (""Eagle"", ""Kiwi"") AND (c[""Discriminator""] = ""Kiwi"")) +OFFSET 0 LIMIT @__p_0"); + } + + public override async Task Union_entity_equality(bool async) + { + await base.Union_entity_equality(async); + + AssertSql(" "); + } + + public override void Setting_foreign_key_to_a_different_type_throws() + { + base.Setting_foreign_key_to_a_different_type_throws(); + + AssertSql( + @"SELECT c +FROM root c +WHERE (c[""Discriminator""] = ""Kiwi"") +OFFSET 0 LIMIT 2"); + } + + public override async Task Byte_enum_value_constant_used_in_projection(bool async) + { + await base.Byte_enum_value_constant_used_in_projection(async); + + AssertSql( + @"SELECT VALUE {""c"" : (c[""IsFlightless""] ? 0 : 1)} +FROM root c +WHERE (c[""Discriminator""] = ""Kiwi"")"); + } + + public override void Member_access_on_intermediate_type_works() + { + base.Member_access_on_intermediate_type_works(); + + AssertSql( + @"SELECT c[""Name""] +FROM root c +WHERE (c[""Discriminator""] = ""Kiwi"") +ORDER BY c[""Name""]"); + } + + [ConditionalTheory(Skip = "Issue#17246 subquery usage")] + public override async Task Is_operator_on_result_of_FirstOrDefault(bool async) + { + await base.Is_operator_on_result_of_FirstOrDefault(async); + + AssertSql(" "); + } + + protected override bool EnforcesFkConstraints => false; + + private void AssertSql(params string[] expected) + => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); + + protected override void ClearLog() + => Fixture.TestSqlLoggerFactory.Clear(); + } +} diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindJoinQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindJoinQueryCosmosTest.cs deleted file mode 100644 index 4de9799d559..00000000000 --- a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindJoinQueryCosmosTest.cs +++ /dev/null @@ -1,537 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. - -using System.Linq; -using System.Threading.Tasks; -using Microsoft.EntityFrameworkCore.TestModels.Northwind; -using Microsoft.EntityFrameworkCore.TestUtilities; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.EntityFrameworkCore.Query -{ - public class NorthwindJoinQueryCosmosTest : NorthwindJoinQueryTestBase> - { - public NorthwindJoinQueryCosmosTest( - NorthwindQueryCosmosFixture fixture, - ITestOutputHelper testOutputHelper) - : base(fixture) - { - ClearLog(); - //Fixture.TestSqlLoggerFactory.SetTestOutputHelper(testOutputHelper); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task Join_customers_orders_projection(bool async) - { - await base.Join_customers_orders_projection(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task Join_customers_orders_entities(bool async) - { - await base.Join_customers_orders_entities(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue #17246")] - public override Task Join_customers_orders_entities_same_entity_twice(bool async) - { - return base.Join_customers_orders_entities_same_entity_twice(async); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task Join_select_many(bool async) - { - await AssertQuery( - async, - ss => from c in ss.Set().Where(c => c.CustomerID == "ALFKI") - join o in ss.Set() on c.CustomerID equals o.CustomerID - from e in ss.Set() - select new - { - c, - o, - e - }, - e => e.c.CustomerID + " " + e.o.OrderID + " " + e.e.EmployeeID, - entryCount: 16); - - AssertSql( - @"SELECT c -FROM root c -WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""CustomerID""] = ""ALFKI""))", - // - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Order"")", - // - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Employee"")", - // - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Employee"")", - // - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Employee"")", - // - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Employee"")", - // - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Employee"")", - // - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Employee"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task Client_Join_select_many(bool async) - { - await base.Client_Join_select_many(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Employee"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task Join_customers_orders_select(bool async) - { - await base.Join_customers_orders_select(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task Join_customers_orders_with_subquery(bool async) - { - await base.Join_customers_orders_with_subquery(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task Join_customers_orders_with_subquery_with_take(bool async) - { - await base.Join_customers_orders_with_subquery_with_take(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task Join_customers_orders_with_subquery_anonymous_property_method(bool async) - { - await base.Join_customers_orders_with_subquery_anonymous_property_method(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task Join_customers_orders_with_subquery_anonymous_property_method_with_take(bool async) - { - await base.Join_customers_orders_with_subquery_anonymous_property_method_with_take(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task Join_customers_orders_with_subquery_predicate(bool async) - { - await base.Join_customers_orders_with_subquery_predicate(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task Join_customers_orders_with_subquery_predicate_with_take(bool async) - { - await base.Join_customers_orders_with_subquery_predicate_with_take(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task Join_composite_key(bool async) - { - await base.Join_composite_key(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task Join_complex_condition(bool async) - { - await base.Join_complex_condition(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""CustomerID""] = ""ALFKI""))"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task Join_same_collection_multiple(bool async) - { - await base.Join_same_collection_multiple(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task Join_same_collection_force_alias_uniquefication(bool async) - { - await base.Join_same_collection_force_alias_uniquefication(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Order"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override Task GroupJoin_customers_employees_shadow(bool async) - { - return base.GroupJoin_customers_employees_shadow(async); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override Task GroupJoin_customers_employees_subquery_shadow(bool async) - { - return base.GroupJoin_customers_employees_subquery_shadow(async); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override Task GroupJoin_customers_employees_subquery_shadow_take(bool async) - { - return base.GroupJoin_customers_employees_subquery_shadow_take(async); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override Task GroupJoin_projection(bool async) - { - return base.GroupJoin_projection(async); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task GroupJoin_simple(bool async) - { - await base.GroupJoin_simple(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task GroupJoin_simple2(bool async) - { - await base.GroupJoin_simple2(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task GroupJoin_simple3(bool async) - { - await base.GroupJoin_simple3(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task GroupJoin_simple_ordering(bool async) - { - await base.GroupJoin_simple_ordering(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task GroupJoin_simple_subquery(bool async) - { - await base.GroupJoin_simple_subquery(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task GroupJoin_DefaultIfEmpty(bool async) - { - await base.GroupJoin_DefaultIfEmpty(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task GroupJoin_DefaultIfEmpty_multiple(bool async) - { - await base.GroupJoin_DefaultIfEmpty_multiple(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task GroupJoin_DefaultIfEmpty2(bool async) - { - await base.GroupJoin_DefaultIfEmpty2(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Employee"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task GroupJoin_DefaultIfEmpty3(bool async) - { - await base.GroupJoin_DefaultIfEmpty3(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task GroupJoin_Where(bool async) - { - await base.GroupJoin_Where(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task GroupJoin_Where_OrderBy(bool async) - { - await base.GroupJoin_Where_OrderBy(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task GroupJoin_DefaultIfEmpty_Where(bool async) - { - await base.GroupJoin_DefaultIfEmpty_Where(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task Join_GroupJoin_DefaultIfEmpty_Where(bool async) - { - await base.Join_GroupJoin_DefaultIfEmpty_Where(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task GroupJoin_DefaultIfEmpty_Project(bool async) - { - await base.GroupJoin_DefaultIfEmpty_Project(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task GroupJoin_SelectMany_subquery_with_filter(bool async) - { - await base.GroupJoin_SelectMany_subquery_with_filter(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task GroupJoin_SelectMany_subquery_with_filter_orderby(bool async) - { - await base.GroupJoin_SelectMany_subquery_with_filter_orderby(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task GroupJoin_SelectMany_subquery_with_filter_and_DefaultIfEmpty(bool async) - { - await base.GroupJoin_SelectMany_subquery_with_filter_and_DefaultIfEmpty(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task GroupJoin_SelectMany_subquery_with_filter_orderby_and_DefaultIfEmpty(bool async) - { - await base.GroupJoin_SelectMany_subquery_with_filter_orderby_and_DefaultIfEmpty(async); - - AssertSql( - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Customer"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override async Task GroupJoin_subquery_projection_outer_mixed(bool async) - { - await AssertQuery( - async, - ss => - from c in ss.Set().Where(c => c.CustomerID == "ALFKI") - from o0 in ss.Set().OrderBy(o => o.OrderID).Take(1) - join o1 in ss.Set() on c.CustomerID equals o1.CustomerID into orders - from o2 in orders - select new - { - A = c.CustomerID, - B = o0.CustomerID, - C = o2.CustomerID - }, - e => (e.A, e.B, e.C)); - - AssertSql( - @"SELECT c -FROM root c -WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""CustomerID""] = ""ALFKI""))", - // - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Order"")", - // - @"SELECT c -FROM root c -WHERE (c[""Discriminator""] = ""Order"")"); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override Task GroupJoin_Subquery_with_Take_Then_SelectMany_Where(bool async) - { - return base.GroupJoin_Subquery_with_Take_Then_SelectMany_Where(async); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override Task Inner_join_with_tautology_predicate_converts_to_cross_join(bool async) - { - return base.Inner_join_with_tautology_predicate_converts_to_cross_join(async); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override Task Left_join_with_tautology_predicate_doesnt_convert_to_cross_join(bool async) - { - return base.Left_join_with_tautology_predicate_doesnt_convert_to_cross_join(async); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override Task SelectMany_with_client_eval(bool async) - { - return base.SelectMany_with_client_eval(async); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override Task SelectMany_with_client_eval_with_collection_shaper(bool async) - { - return base.SelectMany_with_client_eval_with_collection_shaper(async); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override Task SelectMany_with_client_eval_with_collection_shaper_ignored(bool async) - { - return base.SelectMany_with_client_eval_with_collection_shaper_ignored(async); - } - - [ConditionalTheory(Skip = "Issue#17246")] - public override Task SelectMany_with_client_eval_with_constructor(bool async) - { - return base.SelectMany_with_client_eval_with_constructor(async); - } - - private void AssertSql(params string[] expected) - => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); - - protected override void ClearLog() - => Fixture.TestSqlLoggerFactory.Clear(); - } -} diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindWhereQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindWhereQueryCosmosTest.cs index 5e90bca8708..66531046563 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindWhereQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindWhereQueryCosmosTest.cs @@ -478,6 +478,12 @@ public override async Task Where_simple_closure_via_query_cache(bool async) AssertSql( @"@__city_0='London' +SELECT c +FROM root c +WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""City""] = @__city_0))", + // + @"@__city_0='Seattle' + SELECT c FROM root c WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""City""] = @__city_0))"); @@ -528,6 +534,12 @@ public override async Task Where_method_call_closure_via_query_cache(bool async) AssertSql( @"@__GetCity_0='London' +SELECT c +FROM root c +WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""City""] = @__GetCity_0))", + // + @"@__GetCity_0='Seattle' + SELECT c FROM root c WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""City""] = @__GetCity_0))"); @@ -540,6 +552,12 @@ public override async Task Where_field_access_closure_via_query_cache(bool async AssertSql( @"@__city_InstanceFieldValue_0='London' +SELECT c +FROM root c +WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""City""] = @__city_InstanceFieldValue_0))", + // + @"@__city_InstanceFieldValue_0='Seattle' + SELECT c FROM root c WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""City""] = @__city_InstanceFieldValue_0))"); @@ -552,6 +570,12 @@ public override async Task Where_property_access_closure_via_query_cache(bool as AssertSql( @"@__city_InstancePropertyValue_0='London' +SELECT c +FROM root c +WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""City""] = @__city_InstancePropertyValue_0))", + // + @"@__city_InstancePropertyValue_0='Seattle' + SELECT c FROM root c WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""City""] = @__city_InstancePropertyValue_0))"); @@ -564,6 +588,12 @@ public override async Task Where_static_field_access_closure_via_query_cache(boo AssertSql( @"@__StaticFieldValue_0='London' +SELECT c +FROM root c +WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""City""] = @__StaticFieldValue_0))", + // + @"@__StaticFieldValue_0='Seattle' + SELECT c FROM root c WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""City""] = @__StaticFieldValue_0))"); @@ -576,6 +606,12 @@ public override async Task Where_static_property_access_closure_via_query_cache( AssertSql( @"@__StaticPropertyValue_0='London' +SELECT c +FROM root c +WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""City""] = @__StaticPropertyValue_0))", + // + @"@__StaticPropertyValue_0='Seattle' + SELECT c FROM root c WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""City""] = @__StaticPropertyValue_0))"); @@ -588,6 +624,12 @@ public override async Task Where_nested_field_access_closure_via_query_cache(boo AssertSql( @"@__city_Nested_InstanceFieldValue_0='London' +SELECT c +FROM root c +WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""City""] = @__city_Nested_InstanceFieldValue_0))", + // + @"@__city_Nested_InstanceFieldValue_0='Seattle' + SELECT c FROM root c WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""City""] = @__city_Nested_InstanceFieldValue_0))"); @@ -600,6 +642,12 @@ public override async Task Where_nested_property_access_closure_via_query_cache( AssertSql( @"@__city_Nested_InstancePropertyValue_0='London' +SELECT c +FROM root c +WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""City""] = @__city_Nested_InstancePropertyValue_0))", + // + @"@__city_Nested_InstancePropertyValue_0='Seattle' + SELECT c FROM root c WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""City""] = @__city_Nested_InstancePropertyValue_0))"); @@ -630,6 +678,12 @@ public override async Task Where_new_instance_field_access_closure_via_query_cac AssertSql( @"@__InstanceFieldValue_0='London' +SELECT c +FROM root c +WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""City""] = @__InstanceFieldValue_0))", + // + @"@__InstanceFieldValue_0='Seattle' + SELECT c FROM root c WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""City""] = @__InstanceFieldValue_0))"); @@ -1527,7 +1581,11 @@ public override async Task Where_bool_closure(bool async) AssertSql( @"SELECT c FROM root c -WHERE ((c[""Discriminator""] = ""Customer"") AND false)"); +WHERE ((c[""Discriminator""] = ""Customer"") AND false)", + // + @"SELECT c +FROM root c +WHERE ((c[""Discriminator""] = ""Customer"") AND ((c[""CustomerID""] = ""ALFKI"") AND true))"); } public override async Task Where_default(bool async) @@ -1775,7 +1833,6 @@ FROM root c WHERE ((c[""Discriminator""] = ""Customer"") AND ((c[""City""] = null) AND (c[""Country""] = ""UK"")))"); } - [ConditionalTheory(Skip = "Issue #17246")] public override async Task Where_Is_on_same_type(bool async) { await base.Where_Is_on_same_type(async); @@ -1783,7 +1840,7 @@ public override async Task Where_Is_on_same_type(bool async) AssertSql( @"SELECT c FROM root c -WHERE ((c[""Discriminator""] = ""Customer"") AND (c[""Discriminator""] = ""Customer""))"); +WHERE (c[""Discriminator""] = ""Customer"")"); } public override async Task Where_chain(bool async) @@ -1925,10 +1982,14 @@ public override Task Decimal_cast_to_double_works(bool async) return base.Decimal_cast_to_double_works(async); } - [ConditionalTheory(Skip = "Issue#16391")] - public override Task Where_is_conditional(bool async) + public override async Task Where_is_conditional(bool async) { - return base.Where_is_conditional(async); + await base.Where_is_conditional(async); + + AssertSql( + @"SELECT c +FROM root c +WHERE ((c[""Discriminator""] = ""Product"") AND (true ? false : true))"); } [ConditionalTheory(Skip = "Issue#17246")] diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/OwnedQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/OwnedQueryCosmosTest.cs index 77d93f0df61..fff4a382d72 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/OwnedQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/OwnedQueryCosmosTest.cs @@ -217,10 +217,14 @@ public override Task Query_with_owned_entity_equality_object_method(bool async) return base.Query_with_owned_entity_equality_object_method(async); } - [ConditionalTheory(Skip = "OfType #17246")] - public override Task Query_with_OfType_eagerly_loads_correct_owned_navigations(bool async) + public override async Task Query_with_OfType_eagerly_loads_correct_owned_navigations(bool async) { - return base.Query_with_OfType_eagerly_loads_correct_owned_navigations(async); + await base.Query_with_OfType_eagerly_loads_correct_owned_navigations(async); + + AssertSql( + @"SELECT c +FROM root c +WHERE (c[""Discriminator""] IN (""OwnedPerson"", ""Branch"", ""LeafB"", ""LeafA"") AND (c[""Discriminator""] = ""LeafA""))"); } [ConditionalTheory(Skip = "Distinct ordering #16156")] diff --git a/test/EFCore.Cosmos.FunctionalTests/TestUtilities/TestSqlLoggerFactory.cs b/test/EFCore.Cosmos.FunctionalTests/TestUtilities/TestSqlLoggerFactory.cs index bd9cb0a765a..cb6ccde53e4 100644 --- a/test/EFCore.Cosmos.FunctionalTests/TestUtilities/TestSqlLoggerFactory.cs +++ b/test/EFCore.Cosmos.FunctionalTests/TestUtilities/TestSqlLoggerFactory.cs @@ -43,6 +43,8 @@ public void AssertBaseline(string[] expected, bool assertOrder = true) { Assert.Equal(expected[i], SqlStatements[i], ignoreLineEndingDifferences: true); } + + Assert.Empty(SqlStatements.Skip(expected.Length)); } else { @@ -61,11 +63,11 @@ public void AssertBaseline(string[] expected, bool assertOrder = true) new[] { _eol }, StringSplitOptions.RemoveEmptyEntries)[3].Substring(6); - var testName = methodCallLine.Substring(0, methodCallLine.IndexOf(')') + 1); - var lineIndex = methodCallLine.LastIndexOf("line", StringComparison.Ordinal); - var lineNumber = lineIndex > 0 ? methodCallLine.Substring(lineIndex) : ""; - - const string indent = FileNewLine + " "; + var indexMethodEnding = methodCallLine.IndexOf(')') + 1; + var testName = methodCallLine.Substring(0, indexMethodEnding); + var parts = methodCallLine[indexMethodEnding..].Split(" ", StringSplitOptions.RemoveEmptyEntries); + var fileName = parts[1][..^5]; + var lineNumber = int.Parse(parts[2]); var currentDirectory = Directory.GetCurrentDirectory(); var logFile = currentDirectory.Substring( @@ -74,6 +76,7 @@ public void AssertBaseline(string[] expected, bool assertOrder = true) + "QueryBaseline.txt"; var testInfo = testName + " : " + lineNumber + FileNewLine; + const string indent = FileNewLine + " "; var newBaseLine = $@" AssertSql( {string.Join("," + indent + "//" + indent, SqlStatements.Take(9).Select(sql => "@\"" + sql.Replace("\"", "\"\"") + "\""))}); @@ -88,7 +91,7 @@ public void AssertBaseline(string[] expected, bool assertOrder = true) Logger.TestOutputHelper?.WriteLine("---- New Baseline -------------------------------------------------------------------"); Logger.TestOutputHelper?.WriteLine(newBaseLine); - var contents = testInfo + newBaseLine + FileNewLine + FileNewLine; + var contents = testInfo + newBaseLine + FileNewLine + "--------------------" + FileNewLine; File.AppendAllText(logFile, contents); diff --git a/test/EFCore.Relational.Specification.Tests/TestUtilities/TestSqlLoggerFactory.cs b/test/EFCore.Relational.Specification.Tests/TestUtilities/TestSqlLoggerFactory.cs index a0d453e21be..9a3ada9e6c7 100644 --- a/test/EFCore.Relational.Specification.Tests/TestUtilities/TestSqlLoggerFactory.cs +++ b/test/EFCore.Relational.Specification.Tests/TestUtilities/TestSqlLoggerFactory.cs @@ -66,7 +66,6 @@ public void AssertBaseline(string[] expected, bool assertOrder = true) } catch { - var writeToLog = true; var methodCallLine = Environment.StackTrace.Split( new[] { _eol }, StringSplitOptions.RemoveEmptyEntries)[3].Substring(6); @@ -77,65 +76,31 @@ public void AssertBaseline(string[] expected, bool assertOrder = true) var fileName = parts[1][..^5]; var lineNumber = int.Parse(parts[2]); - if (writeToLog || SqlStatements.Count > 9) - { - var currentDirectory = Directory.GetCurrentDirectory(); - var logFile = currentDirectory.Substring( - 0, - currentDirectory.LastIndexOf("\\artifacts\\", StringComparison.Ordinal) + 1) - + "QueryBaseline.txt"; + var currentDirectory = Directory.GetCurrentDirectory(); + var logFile = currentDirectory.Substring( + 0, + currentDirectory.LastIndexOf("\\artifacts\\", StringComparison.Ordinal) + 1) + + "QueryBaseline.txt"; - var testInfo = testName + " : " + lineNumber + FileNewLine; - const string indent = FileNewLine + " "; + var testInfo = testName + " : " + lineNumber + FileNewLine; + const string indent = FileNewLine + " "; - var newBaseLine = $@" AssertSql( + var newBaseLine = $@" AssertSql( {string.Join("," + indent + "//" + indent, SqlStatements.Take(9).Select(sql => "@\"" + sql.Replace("\"", "\"\"") + "\""))}); "; - if (SqlStatements.Count > 9) - { - newBaseLine += "Output truncated."; - } - - Logger.TestOutputHelper?.WriteLine("---- New Baseline -------------------------------------------------------------------"); - Logger.TestOutputHelper?.WriteLine(newBaseLine); + if (SqlStatements.Count > 9) + { + newBaseLine += "Output truncated."; + } - var contents = testInfo + newBaseLine + FileNewLine + "--------------------" + FileNewLine; + Logger.TestOutputHelper?.WriteLine("---- New Baseline -------------------------------------------------------------------"); + Logger.TestOutputHelper?.WriteLine(newBaseLine); - File.AppendAllText(logFile, contents); - } - else - { - var indentCount = 3; - var initialIndent = string.Join("", Enumerable.Repeat(" ", indentCount)); - var additionalIndent = initialIndent + " "; - var existingLines = File.ReadAllLines(fileName); - var newBaseLine = $@"{initialIndent}AssertSql( -{additionalIndent}{string.Join("," + FileNewLine + additionalIndent + "//" + FileNewLine + additionalIndent, SqlStatements.Take(9).Select(sql => "@\"" + sql.Replace("\"", "\"\"") + "\""))});"; - var newLines = newBaseLine.Split(Environment.NewLine); - using (var fileStream = File.Open(fileName, FileMode.Open)) - { - using (var streamWriter = new StreamWriter(fileStream)) - { - for (var i = 1; i <= existingLines.Length; i++) - { - if (i == lineNumber) - { - for (var j = 0; j < newLines.Length; i++, j++) - { - streamWriter.WriteLine(newLines[j]); - } - } - - streamWriter.WriteLine(existingLines[i - 1]); - } - } - } + var contents = testInfo + newBaseLine + FileNewLine + "--------------------" + FileNewLine; - Logger.TestOutputHelper?.WriteLine("---- New Baseline -------------------------------------------------------------------"); - Logger.TestOutputHelper?.WriteLine(newBaseLine); - } + File.AppendAllText(logFile, contents); throw; } diff --git a/test/EFCore.Specification.Tests/Query/NorthwindWhereQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/NorthwindWhereQueryTestBase.cs index aa989d34812..9794859c710 100644 --- a/test/EFCore.Specification.Tests/Query/NorthwindWhereQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/NorthwindWhereQueryTestBase.cs @@ -1943,8 +1943,6 @@ public virtual Task Decimal_cast_to_double_works(bool async) [MemberData(nameof(IsAsyncData))] public virtual Task Where_is_conditional(bool async) { - var customer = new Customer(); - return AssertQuery( async, ss => ss.Set().Where(p => p is Product ? false : true)); diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs index 432db54bd79..84ccd789316 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs @@ -2972,7 +2972,6 @@ public override async Task Member_access_on_derived_entity_using_cast(bool async AssertSql( @"SELECT [f].[Name], [f].[Eradicated] FROM [Factions] AS [f] -WHERE [f].[Discriminator] = N'LocustHorde' ORDER BY [f].[Name]"); } @@ -2983,7 +2982,6 @@ public override async Task Member_access_on_derived_materialized_entity_using_ca AssertSql( @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated] FROM [Factions] AS [f] -WHERE [f].[Discriminator] = N'LocustHorde' ORDER BY [f].[Name]"); } @@ -2994,7 +2992,6 @@ public override async Task Member_access_on_derived_entity_using_cast_and_let(bo AssertSql( @"SELECT [f].[Name], [f].[Eradicated] FROM [Factions] AS [f] -WHERE [f].[Discriminator] = N'LocustHorde' ORDER BY [f].[Name]"); } @@ -3005,7 +3002,6 @@ public override async Task Property_access_on_derived_entity_using_cast(bool asy AssertSql( @"SELECT [f].[Name], [f].[Eradicated] FROM [Factions] AS [f] -WHERE [f].[Discriminator] = N'LocustHorde' ORDER BY [f].[Name]"); } @@ -3021,7 +3017,6 @@ LEFT JOIN ( FROM [LocustLeaders] AS [l] WHERE [l].[Discriminator] = N'LocustCommander' ) AS [t] ON [f].[CommanderName] = [t].[Name] -WHERE [f].[Discriminator] = N'LocustHorde' ORDER BY [f].[Name]"); } @@ -3037,7 +3032,6 @@ LEFT JOIN ( FROM [LocustLeaders] AS [l] WHERE [l].[Discriminator] = N'LocustCommander' ) AS [t] ON [f].[CommanderName] = [t].[Name] -WHERE [f].[Discriminator] = N'LocustHorde' ORDER BY [f].[Name]"); } @@ -3053,7 +3047,6 @@ LEFT JOIN ( FROM [LocustLeaders] AS [l] WHERE [l].[Discriminator] = N'LocustCommander' ) AS [t] ON [f].[CommanderName] = [t].[Name] -WHERE [f].[Discriminator] = N'LocustHorde' ORDER BY [f].[Name]"); } @@ -3069,7 +3062,6 @@ LEFT JOIN ( FROM [LocustLeaders] AS [l] WHERE [l].[Discriminator] = N'LocustCommander' ) AS [t] ON [f].[CommanderName] = [t].[Name] -WHERE [f].[Discriminator] = N'LocustHorde' ORDER BY [f].[Name]"); } @@ -3083,7 +3075,6 @@ SELECT COUNT(*) FROM [LocustLeaders] AS [l] WHERE [f].[Id] = [l].[LocustHordeId]) AS [LeadersCount] FROM [Factions] AS [f] -WHERE [f].[Discriminator] = N'LocustHorde' ORDER BY [f].[Name]"); } @@ -3095,7 +3086,6 @@ public override async Task Collection_navigation_access_on_derived_entity_using_ @"SELECT [f].[Name], [l].[Name] AS [LeaderName] FROM [Factions] AS [f] INNER JOIN [LocustLeaders] AS [l] ON [f].[Id] = [l].[LocustHordeId] -WHERE [f].[Discriminator] = N'LocustHorde' ORDER BY [l].[Name]"); } @@ -3166,7 +3156,7 @@ FROM [LocustLeaders] AS [l] WHERE [l].[Discriminator] = N'LocustCommander' ) AS [t0] ON [f].[CommanderName] = [t0].[Name] LEFT JOIN [Gears] AS [g0] ON ([t0].[DefeatedByNickname] = [g0].[Nickname]) AND ([t0].[DefeatedBySquadId] = [g0].[SquadId]) -WHERE (([f].[Discriminator] = N'LocustHorde') AND ([t].[HasSoulPatch] = CAST(1 AS bit))) AND (([g0].[Nickname] = [t].[Nickname]) AND ([g0].[SquadId] = [t].[SquadId]))"); +WHERE ([t].[HasSoulPatch] = CAST(1 AS bit)) AND (([g0].[Nickname] = [t].[Nickname]) AND ([g0].[SquadId] = [t].[SquadId]))"); } public override async Task Comparing_entities_using_Equals_inheritance(bool async) @@ -3219,8 +3209,7 @@ public override async Task Select_null_conditional_with_inheritance(bool async) WHEN [f].[CommanderName] IS NOT NULL THEN [f].[CommanderName] ELSE NULL END -FROM [Factions] AS [f] -WHERE [f].[Discriminator] = N'LocustHorde'"); +FROM [Factions] AS [f]"); } public override async Task Select_null_conditional_with_inheritance_negative(bool async) @@ -3232,8 +3221,7 @@ public override async Task Select_null_conditional_with_inheritance_negative(boo WHEN [f].[CommanderName] IS NOT NULL THEN [f].[Eradicated] ELSE NULL END -FROM [Factions] AS [f] -WHERE [f].[Discriminator] = N'LocustHorde'"); +FROM [Factions] AS [f]"); } public override async Task Project_collection_navigation_with_inheritance1(bool async) @@ -3284,7 +3272,6 @@ FROM [LocustLeaders] AS [l] ) AS [t] ON [f].[CommanderName] = [t].[Name] LEFT JOIN [Gears] AS [g] ON ([t].[DefeatedByNickname] = [g].[Nickname]) AND ([t].[DefeatedBySquadId] = [g].[SquadId]) LEFT JOIN [Gears] AS [g0] ON (([g].[Nickname] = [g0].[LeaderNickname]) OR ([g].[Nickname] IS NULL AND [g0].[LeaderNickname] IS NULL)) AND ([g].[SquadId] = [g0].[LeaderSquadId]) -WHERE [f].[Discriminator] = N'LocustHorde' ORDER BY [f].[Id], [t].[Name], [g].[Nickname], [g].[SquadId], [g0].[Nickname], [g0].[SquadId]"); } @@ -6017,7 +6004,7 @@ LEFT JOIN ( FROM [LocustLeaders] AS [l] WHERE [l].[Discriminator] = N'LocustCommander' ) AS [t] ON [f].[CommanderName] = [t].[Name] -WHERE ([f].[Discriminator] = N'LocustHorde') AND [t].[Name] IS NOT NULL"); +WHERE [t].[Name] IS NOT NULL"); } public override async Task Navigation_based_on_complex_expression3(bool async) @@ -6031,8 +6018,7 @@ LEFT JOIN ( SELECT [l].[Name], [l].[Discriminator], [l].[LocustHordeId], [l].[ThreatLevel], [l].[ThreatLevelByte], [l].[ThreatLevelNullableByte], [l].[DefeatedByNickname], [l].[DefeatedBySquadId], [l].[HighCommandId] FROM [LocustLeaders] AS [l] WHERE [l].[Discriminator] = N'LocustCommander' -) AS [t] ON [f].[CommanderName] = [t].[Name] -WHERE [f].[Discriminator] = N'LocustHorde'"); +) AS [t] ON [f].[CommanderName] = [t].[Name]"); } public override async Task Navigation_based_on_complex_expression4(bool async)