From 84860c8df82e6a544227bea0896d54b441d28981 Mon Sep 17 00:00:00 2001 From: AndriySvyryd Date: Thu, 27 Jun 2019 18:06:05 -0700 Subject: [PATCH] Add support for nested navigations in filters Part of #12086 --- .../Infrastructure/CosmosModelValidator.cs | 3 +- ...yableMethodTranslatingExpressionVisitor.cs | 4 +- .../CosmosSqlTranslatingExpressionVisitor.cs | 69 ++++++--- .../Pipeline/EntityProjectionExpression.cs | 19 +++ .../Query/Pipeline/KeyAccessExpression.cs | 21 +-- .../Query/Pipeline/ObjectAccessExpression.cs | 62 ++++++++ .../Query/Pipeline/ProjectionExpression.cs | 5 +- .../Query/Pipeline/QuerySqlGenerator.cs | 7 + .../Query/Pipeline/SelectExpression.cs | 10 +- .../Query/Pipeline/SqlExpressionVisitor.cs | 1 + .../Pipeline/ShapedQueryExpressionVisitor.cs | 13 +- .../Query/OwnedQueryCosmosTest.cs | 136 +++++++++++++++++- .../Query/OwnedQueryTestBase.cs | 3 +- .../Query/OwnedQuerySqlServerTest.cs | 4 +- 14 files changed, 302 insertions(+), 55 deletions(-) create mode 100644 src/EFCore.Cosmos/Query/Pipeline/ObjectAccessExpression.cs diff --git a/src/EFCore.Cosmos/Infrastructure/CosmosModelValidator.cs b/src/EFCore.Cosmos/Infrastructure/CosmosModelValidator.cs index c67b8e171ff..f9d6dd98d94 100644 --- a/src/EFCore.Cosmos/Infrastructure/CosmosModelValidator.cs +++ b/src/EFCore.Cosmos/Infrastructure/CosmosModelValidator.cs @@ -143,7 +143,8 @@ public override void Validate(IModel model, IDiagnosticsLogger _sqlTranslator.Translate(expression); private SqlExpression TranslateLambdaExpression( ShapedQueryExpression shapedQueryExpression, LambdaExpression lambdaExpression) diff --git a/src/EFCore.Cosmos/Query/Pipeline/CosmosSqlTranslatingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Pipeline/CosmosSqlTranslatingExpressionVisitor.cs index b16a2bb2e88..036cac34705 100644 --- a/src/EFCore.Cosmos/Query/Pipeline/CosmosSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Pipeline/CosmosSqlTranslatingExpressionVisitor.cs @@ -2,13 +2,12 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Linq.Expressions; -using System.Reflection; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Metadata.Internal; using Microsoft.EntityFrameworkCore.Query.Expressions.Internal; using Microsoft.EntityFrameworkCore.Query.Pipeline; @@ -55,7 +54,8 @@ private class SqlTypeMappingVerifyingExpressionVisitor : ExpressionVisitor { protected override Expression VisitExtension(Expression node) { - if (node is SqlExpression sqlExpression) + if (node is SqlExpression sqlExpression + && !(node is ObjectAccessExpression)) { if (sqlExpression.TypeMapping == null) { @@ -69,42 +69,73 @@ protected override Expression VisitExtension(Expression node) protected override Expression VisitMember(MemberExpression memberExpression) { - if (memberExpression.Expression is EntityShaperExpression) + var innerExpression = Visit(memberExpression.Expression); + + if (TryBindProperty(innerExpression, MemberIdentity.Create(memberExpression.Member), out var result)) { - return BindProperty(memberExpression.Expression, memberExpression.Member.GetSimpleMemberName()); + return result; } - var innerExpression = Visit(memberExpression.Expression); - return TranslationFailed(memberExpression.Expression, innerExpression) ? null : _memberTranslatorProvider.Translate((SqlExpression)innerExpression, memberExpression.Member, memberExpression.Type); } - private SqlExpression BindProperty(Expression source, string propertyName) + private bool TryBindProperty(Expression source, MemberIdentity member, out SqlExpression expression) { - if (source is EntityShaperExpression entityShaper) + if (source is EntityShaperExpression entityShaperExpression) { - var entityType = entityShaper.EntityType; + var projectionBindingExpression = (ProjectionBindingExpression)entityShaperExpression.ValueBufferExpression; + var selectExpression = ((SelectExpression)projectionBindingExpression.QueryExpression); + + var entityType = entityShaperExpression.EntityType; + var property = member.MemberInfo != null + ? entityType.FindProperty(member.MemberInfo) + : entityType.FindProperty(member.Name); + if (property != null) + { + expression = selectExpression.BindProperty(property, projectionBindingExpression); + return true; + } - return BindProperty(entityShaper, entityType.FindProperty(propertyName)); + var navigation = member.MemberInfo != null + ? entityType.FindNavigation(member.MemberInfo) + : entityType.FindNavigation(member.Name); + expression = selectExpression.BindNavigation(navigation, projectionBindingExpression); + return true; } + else if (source is ObjectAccessExpression objectAccessExpression) + { + var entityType = objectAccessExpression.Navigation.GetTargetType(); + var property = member.MemberInfo != null + ? entityType.FindProperty(member.MemberInfo) + : entityType.FindProperty(member.Name); + if (property != null) + { + expression = new KeyAccessExpression(property, objectAccessExpression); + return true; + } - throw new InvalidOperationException(); - } + var navigation = member.MemberInfo != null + ? entityType.FindNavigation(member.MemberInfo) + : entityType.FindNavigation(member.Name); + expression = new ObjectAccessExpression(navigation, objectAccessExpression); + return true; + } - private SqlExpression BindProperty(EntityShaperExpression entityShaperExpression, IProperty property) - { - var projectionBindingExpression = (ProjectionBindingExpression)entityShaperExpression.ValueBufferExpression; - return ((SelectExpression)projectionBindingExpression.QueryExpression) - .BindProperty(projectionBindingExpression, property); + expression = null; + return false; } protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression) { if (methodCallExpression.TryGetEFPropertyArguments(out var source, out var propertyName)) { - return BindProperty(source, propertyName); + if (!TryBindProperty(source, MemberIdentity.Create(propertyName), out var result)) + { + throw new InvalidOperationException(); + } + return result; } //if (methodCallExpression.Method.DeclaringType == typeof(Queryable)) diff --git a/src/EFCore.Cosmos/Query/Pipeline/EntityProjectionExpression.cs b/src/EFCore.Cosmos/Query/Pipeline/EntityProjectionExpression.cs index 6b93749e9b2..9085fd278d5 100644 --- a/src/EFCore.Cosmos/Query/Pipeline/EntityProjectionExpression.cs +++ b/src/EFCore.Cosmos/Query/Pipeline/EntityProjectionExpression.cs @@ -14,6 +14,8 @@ public class EntityProjectionExpression : Expression { private readonly IDictionary _propertyExpressionsCache = new Dictionary(); + private readonly IDictionary _navigationExpressionsCache + = new Dictionary(); private readonly IEntityType _entityType; public EntityProjectionExpression(IEntityType entityType, RootReferenceExpression accessExpression, string alias) @@ -55,5 +57,22 @@ public KeyAccessExpression GetProperty(IProperty property) return expression; } + + public ObjectAccessExpression GetNavigation(INavigation navigation) + { + if (!_entityType.GetTypesInHierarchy().Contains(navigation.DeclaringEntityType)) + { + throw new InvalidOperationException( + $"Called EntityProjectionExpression.GetNavigation() with incorrect INavigation. EntityType:{_entityType.DisplayName()}, Navigation:{navigation.Name}"); + } + + if (!_navigationExpressionsCache.TryGetValue(navigation, out var expression)) + { + expression = new ObjectAccessExpression(navigation, AccessExpression); + _navigationExpressionsCache[navigation] = expression; + } + + return expression; + } } } diff --git a/src/EFCore.Cosmos/Query/Pipeline/KeyAccessExpression.cs b/src/EFCore.Cosmos/Query/Pipeline/KeyAccessExpression.cs index 69a83680e36..2ed66ab3d5b 100644 --- a/src/EFCore.Cosmos/Query/Pipeline/KeyAccessExpression.cs +++ b/src/EFCore.Cosmos/Query/Pipeline/KeyAccessExpression.cs @@ -11,9 +11,9 @@ namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Pipeline public class KeyAccessExpression : SqlExpression { private readonly IProperty _property; - private readonly RootReferenceExpression _outerExpression; + private readonly Expression _outerExpression; - public KeyAccessExpression(IProperty property, RootReferenceExpression outerExpression) + public KeyAccessExpression(IProperty property, Expression outerExpression) : base(property.ClrType, property.GetTypeMapping()) { Name = property.GetCosmosPropertyName(); @@ -25,27 +25,20 @@ public KeyAccessExpression(IProperty property, RootReferenceExpression outerExpr protected override Expression VisitChildren(ExpressionVisitor visitor) { - var outerExpression = (RootReferenceExpression)visitor.Visit(_outerExpression); + var outerExpression = visitor.Visit(_outerExpression); return Update(outerExpression); } - public KeyAccessExpression Update(RootReferenceExpression outerExpression) - { - return outerExpression != _outerExpression + public KeyAccessExpression Update(Expression outerExpression) + => outerExpression != _outerExpression ? new KeyAccessExpression(_property, outerExpression) : this; - } public override void Print(ExpressionPrinter expressionPrinter) - { - expressionPrinter.StringBuilder.Append(ToString()); - } + => expressionPrinter.StringBuilder.Append(ToString()); - public override string ToString() - { - return $"{_outerExpression}[\"{Name}\"]"; - } + public override string ToString() => $"{_outerExpression}[\"{Name}\"]"; public override bool Equals(object obj) => obj != null diff --git a/src/EFCore.Cosmos/Query/Pipeline/ObjectAccessExpression.cs b/src/EFCore.Cosmos/Query/Pipeline/ObjectAccessExpression.cs new file mode 100644 index 00000000000..3169ba6e32a --- /dev/null +++ b/src/EFCore.Cosmos/Query/Pipeline/ObjectAccessExpression.cs @@ -0,0 +1,62 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Query.Internal; + +namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Pipeline +{ + public class ObjectAccessExpression : SqlExpression + { + private readonly Expression _outerExpression; + + public ObjectAccessExpression(INavigation navigation, Expression outerExpression) + : base(navigation.ClrType, null) + { + Name = navigation.GetTargetType().GetCosmosContainingPropertyName(); + if (Name == null) + { + throw new InvalidOperationException( + $"Navigation '{navigation.DeclaringEntityType.DisplayName()}.{navigation.Name}' doesn't point to a nested entity."); + } + + Navigation = navigation; + _outerExpression = outerExpression; + } + + public string Name { get; } + + public INavigation Navigation { get; } + + protected override Expression VisitChildren(ExpressionVisitor visitor) + { + var outerExpression = visitor.Visit(_outerExpression); + + return Update(outerExpression); + } + + public ObjectAccessExpression Update(Expression outerExpression) + => outerExpression != _outerExpression + ? new ObjectAccessExpression(Navigation, outerExpression) + : this; + + public override void Print(ExpressionPrinter expressionPrinter) => expressionPrinter.StringBuilder.Append(ToString()); + + public override string ToString() => $"{_outerExpression}[\"{Name}\"]"; + + public override bool Equals(object obj) + => obj != null + && (ReferenceEquals(this, obj) + || obj is ObjectAccessExpression objectAccessExpression + && Equals(objectAccessExpression)); + + private bool Equals(ObjectAccessExpression objectAccessExpression) + => base.Equals(objectAccessExpression) + && string.Equals(Name, objectAccessExpression.Name) + && _outerExpression.Equals(objectAccessExpression._outerExpression); + + public override int GetHashCode() => HashCode.Combine(base.GetHashCode(), Name, _outerExpression); + } +} diff --git a/src/EFCore.Cosmos/Query/Pipeline/ProjectionExpression.cs b/src/EFCore.Cosmos/Query/Pipeline/ProjectionExpression.cs index 06ba10973ed..096b3d4ba58 100644 --- a/src/EFCore.Cosmos/Query/Pipeline/ProjectionExpression.cs +++ b/src/EFCore.Cosmos/Query/Pipeline/ProjectionExpression.cs @@ -42,10 +42,9 @@ public void Print(ExpressionPrinter expressionPrinter) } private string GetName() - { - return (Expression as KeyAccessExpression)?.Name + => (Expression as KeyAccessExpression)?.Name + ?? (Expression as ObjectAccessExpression)?.Name ?? (Expression as EntityProjectionExpression)?.Alias; - } public override bool Equals(object obj) => obj != null diff --git a/src/EFCore.Cosmos/Query/Pipeline/QuerySqlGenerator.cs b/src/EFCore.Cosmos/Query/Pipeline/QuerySqlGenerator.cs index 3d8a24ca9c3..8f6039ec952 100644 --- a/src/EFCore.Cosmos/Query/Pipeline/QuerySqlGenerator.cs +++ b/src/EFCore.Cosmos/Query/Pipeline/QuerySqlGenerator.cs @@ -82,6 +82,13 @@ protected override Expression VisitKeyAccess(KeyAccessExpression keyAccessExpres return keyAccessExpression; } + protected override Expression VisitObjectAccess(ObjectAccessExpression objectAccessExpression) + { + _sqlBuilder.Append(objectAccessExpression); + + return objectAccessExpression; + } + protected override Expression VisitProjection(ProjectionExpression projectionExpression) { Visit(projectionExpression.Expression); diff --git a/src/EFCore.Cosmos/Query/Pipeline/SelectExpression.cs b/src/EFCore.Cosmos/Query/Pipeline/SelectExpression.cs index ab3c1291387..c09f2d0a925 100644 --- a/src/EFCore.Cosmos/Query/Pipeline/SelectExpression.cs +++ b/src/EFCore.Cosmos/Query/Pipeline/SelectExpression.cs @@ -208,11 +208,13 @@ public void ReverseOrderings() } } - public SqlExpression BindProperty(ProjectionBindingExpression projectionBindingExpression, IProperty property) - { - return ((EntityProjectionExpression)_projectionMapping[projectionBindingExpression.ProjectionMember]) + public SqlExpression BindProperty(IProperty property, ProjectionBindingExpression projectionBindingExpression) + => ((EntityProjectionExpression)_projectionMapping[projectionBindingExpression.ProjectionMember]) .GetProperty(property); - } + + public SqlExpression BindNavigation(INavigation navigation, ProjectionBindingExpression projectionBindingExpression) + => ((EntityProjectionExpression)_projectionMapping[projectionBindingExpression.ProjectionMember]) + .GetNavigation(navigation); public override Type Type => typeof(JObject); public override ExpressionType NodeType => ExpressionType.Extension; diff --git a/src/EFCore.Cosmos/Query/Pipeline/SqlExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Pipeline/SqlExpressionVisitor.cs index 581a134a4c6..2fe0a3d77fb 100644 --- a/src/EFCore.Cosmos/Query/Pipeline/SqlExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Pipeline/SqlExpressionVisitor.cs @@ -63,6 +63,7 @@ protected override Expression VisitExtension(Expression extensionExpression) protected abstract Expression VisitSqlConstant(SqlConstantExpression sqlConstantExpression); protected abstract Expression VisitSqlBinary(SqlBinaryExpression sqlBinaryExpression); protected abstract Expression VisitKeyAccess(KeyAccessExpression keyAccessExpression); + protected abstract Expression VisitObjectAccess(ObjectAccessExpression objectAccessExpression); protected abstract Expression VisitRootReference(RootReferenceExpression rootReferenceExpression); protected abstract Expression VisitEntityProjection(EntityProjectionExpression entityProjectionExpression); protected abstract Expression VisitProjection(ProjectionExpression projectionExpression); diff --git a/src/EFCore/Query/Pipeline/ShapedQueryExpressionVisitor.cs b/src/EFCore/Query/Pipeline/ShapedQueryExpressionVisitor.cs index 86336265c98..09bfec80158 100644 --- a/src/EFCore/Query/Pipeline/ShapedQueryExpressionVisitor.cs +++ b/src/EFCore/Query/Pipeline/ShapedQueryExpressionVisitor.cs @@ -2,7 +2,6 @@ // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using System.Collections; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; @@ -412,28 +411,30 @@ var discriminatorValue { var navigation = nestedShaper.ParentNavigation; var memberInfo = navigation.GetMemberInfo(forConstruction: true, forSet: true); + var convertedInstanceVariable = memberInfo.DeclaringType.IsAssignableFrom(instanceVariable.Type) + ? (Expression)instanceVariable + : Expression.Convert(instanceVariable, memberInfo.DeclaringType); Expression navigationExpression; if (navigation.IsCollection()) { var accessorExpression = Expression.Constant(new ClrCollectionAccessorFactory().Create(navigation)); navigationExpression = Expression.Call(accessorExpression, _accessorAddRangeMethodInfo, - instanceVariable, new CollectionShaperExpression(null, nestedShaper, navigation)); + convertedInstanceVariable, new CollectionShaperExpression(null, nestedShaper, navigation)); } else { navigationExpression = Expression.Assign(Expression.MakeMemberAccess( - instanceVariable, + convertedInstanceVariable, memberInfo), nestedShaper); } - var nestedMaterializer = Expression.Condition( + var nestedMaterializer = Expression.IfThen( Expression.Call(_isAssignableFromMethodInfo, Expression.Constant(navigation.DeclaringEntityType), concreteEntityTypeVariable), - navigationExpression, - Expression.Constant(null, navigationExpression.Type)); + navigationExpression); expressions.Add(nestedMaterializer); } diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/OwnedQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/OwnedQueryCosmosTest.cs index f379beb6629..0a52d7152ef 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/OwnedQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/OwnedQueryCosmosTest.cs @@ -7,11 +7,12 @@ using Microsoft.EntityFrameworkCore.TestUtilities; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; +using Xunit; using Xunit.Abstractions; namespace Microsoft.EntityFrameworkCore.Cosmos.Query { - internal class OwnedQueryCosmosTest : OwnedQueryTestBase + public class OwnedQueryCosmosTest : OwnedQueryTestBase { public OwnedQueryCosmosTest(OwnedQueryCosmosFixture fixture, ITestOutputHelper testOutputHelper) : base(fixture) @@ -29,6 +30,7 @@ public override void Navigation_rewrite_on_owned_collection() WHERE ((c[""Discriminator""] = ""LeafB"") OR ((c[""Discriminator""] = ""LeafA"") OR ((c[""Discriminator""] = ""Branch"") OR (c[""Discriminator""] = ""OwnedPerson""))))"); } + [ConditionalFact(Skip = "Owned collection #12086")] public override void Navigation_rewrite_on_owned_reference_projecting_entity() { base.Navigation_rewrite_on_owned_reference_projecting_entity(); @@ -39,6 +41,138 @@ public override void Navigation_rewrite_on_owned_reference_projecting_entity() WHERE (((c[""Discriminator""] = ""LeafB"") OR ((c[""Discriminator""] = ""LeafA"") OR ((c[""Discriminator""] = ""Branch"") OR (c[""Discriminator""] = ""OwnedPerson"")))) AND (c[""PersonAddress""][""Country""][""Name""] = ""USA""))"); } + [ConditionalFact(Skip = "Owned collection #12086")] + public override void Query_for_base_type_loads_all_owned_navs() + { + base.Query_for_base_type_loads_all_owned_navs(); + } + + [ConditionalFact(Skip = "Owned collection #12086")] + public override void Query_for_branch_type_loads_all_owned_navs() + { + base.Query_for_branch_type_loads_all_owned_navs(); + } + + [ConditionalFact(Skip = "Owned collection #12086")] + public override void Query_for_leaf_type_loads_all_owned_navs() + { + base.Query_for_leaf_type_loads_all_owned_navs(); + } + + [ConditionalFact(Skip = "LeftJoin #12086")] + public override void Filter_owned_entity_chained_with_regular_entity_followed_by_projecting_owned_collection() + { + base.Filter_owned_entity_chained_with_regular_entity_followed_by_projecting_owned_collection(); + } + + [ConditionalFact(Skip = "LeftJoin #12086")] + public override void Navigation_rewrite_on_owned_reference_followed_by_regular_entity() + { + base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity(); + } + + [ConditionalFact(Skip = "LeftJoin #12086")] + public override void Navigation_rewrite_on_owned_reference_followed_by_regular_entity_filter() + { + base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_filter(); + } + + [ConditionalFact(Skip = "LeftJoin #12086")] + public override void Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference() + { + base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference(); + } + + [ConditionalFact(Skip = "LeftJoin #12086")] + public override void Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference_and_scalar() + { + base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference_and_scalar(); + } + + [ConditionalFact(Skip = "LeftJoin #12086")] + public override void Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_collection() + { + base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_collection(); + } + + [ConditionalFact(Skip = "LeftJoin #12086")] + public override void Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_collection_count() + { + base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_collection_count(); + } + + [ConditionalFact(Skip = "LeftJoin #12086")] + public override void Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_property() + { + base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_property(); + } + + [ConditionalFact(Skip = "LeftJoin #12086")] + public override void Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference_in_predicate_and_projection() + { + base.Navigation_rewrite_on_owned_reference_followed_by_regular_entity_and_another_reference_in_predicate_and_projection(); + } + + [ConditionalFact(Skip = "LeftJoin #12086")] + public override void Project_multiple_owned_navigations() + { + base.Project_multiple_owned_navigations(); + } + + [ConditionalFact(Skip = "LeftJoin #12086")] + public override void Project_multiple_owned_navigations_with_expansion_on_owned_collections() + { + base.Project_multiple_owned_navigations_with_expansion_on_owned_collections(); + } + + [ConditionalFact(Skip = "SelectMany #12086")] + public override void SelectMany_on_owned_collection() + { + base.SelectMany_on_owned_collection(); + } + + [ConditionalFact(Skip = "SelectMany #12086")] + public override void SelectMany_on_owned_reference_followed_by_regular_entity_and_collection() + { + base.SelectMany_on_owned_reference_followed_by_regular_entity_and_collection(); + } + + [ConditionalFact(Skip = "SelectMany #12086")] + public override void SelectMany_on_owned_reference_with_entity_in_between_ending_in_owned_collection() + { + base.SelectMany_on_owned_reference_with_entity_in_between_ending_in_owned_collection(); + } + + [ConditionalFact(Skip = "SelectMany #12086")] + public override void Query_with_owned_entity_equality_method() + { + base.Query_with_owned_entity_equality_method(); + } + + [ConditionalFact(Skip = "SelectMany #12086")] + public override void Query_with_owned_entity_equality_object_method() + { + base.Query_with_owned_entity_equality_object_method(); + } + + [ConditionalFact(Skip = "OfType #12086")] + public override void Query_with_OfType_eagerly_loads_correct_owned_navigations() + { + base.Query_with_OfType_eagerly_loads_correct_owned_navigations(); + } + + [ConditionalFact(Skip = "Distinct ordering #16156")] + public override void Query_when_subquery() + { + base.Query_when_subquery(); + } + + [ConditionalFact(Skip = "Count #16146")] + public override void No_ignored_include_warning_when_implicit_load() + { + base.No_ignored_include_warning_when_implicit_load(); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); diff --git a/test/EFCore.Specification.Tests/Query/OwnedQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/OwnedQueryTestBase.cs index e81efc0fed8..f355272fa08 100644 --- a/test/EFCore.Specification.Tests/Query/OwnedQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/OwnedQueryTestBase.cs @@ -234,9 +234,8 @@ public virtual void Navigation_rewrite_on_owned_collection_with_composition_comp } } - [ConditionalFact] - public virtual void Select_many_on_owned_collection() + public virtual void SelectMany_on_owned_collection() { using (var ctx = CreateContext()) { diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/OwnedQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/OwnedQuerySqlServerTest.cs index 3b84865e679..a1e6f3fd519 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/OwnedQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/OwnedQuerySqlServerTest.cs @@ -619,9 +619,9 @@ public override void Navigation_rewrite_on_owned_collection_with_composition_com @""); } - public override void Select_many_on_owned_collection() + public override void SelectMany_on_owned_collection() { - base.Select_many_on_owned_collection(); + base.SelectMany_on_owned_collection(); AssertSql( @"SELECT [p.Orders].[Id], [p.Orders].[ClientId]