From dfd323bc809cd250db93badd56b29811af794f19 Mon Sep 17 00:00:00 2001 From: Arthur Vickers Date: Wed, 7 Aug 2019 07:49:49 -0700 Subject: [PATCH] Reference Include for in-memory provider Part of #16963 --- .../CustomShaperCompilingExpressionVisitor.cs | 161 ++++++ ...emoryProjectionBindingExpressionVisitor.cs | 7 + .../InMemoryShapedQueryExpressionVisitor.cs | 31 +- ...erExpressionProcessingExpressionVisitor.cs | 101 ++++ ...rExpressionProcessingExpressionVisitor.cs} | 0 .../InMemoryComplianceTest.cs | 2 - .../Query/IncludeInMemoryTest.cs | 478 +++++++++++++++++- .../Query/IncludeOneToOneInMemoryTest.cs | 2 +- 8 files changed, 764 insertions(+), 18 deletions(-) create mode 100644 src/EFCore.InMemory/Query/Internal/CustomShaperCompilingExpressionVisitor.cs create mode 100644 src/EFCore.InMemory/Query/Internal/ShaperExpressionProcessingExpressionVisitor.cs rename src/EFCore.Relational/Query/Internal/{ShaperExpressionDedupingExpressionVisitor.cs => ShaperExpressionProcessingExpressionVisitor.cs} (100%) diff --git a/src/EFCore.InMemory/Query/Internal/CustomShaperCompilingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/CustomShaperCompilingExpressionVisitor.cs new file mode 100644 index 00000000000..723bc0999f9 --- /dev/null +++ b/src/EFCore.InMemory/Query/Internal/CustomShaperCompilingExpressionVisitor.cs @@ -0,0 +1,161 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Query; + +namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal +{ + public partial class InMemoryShapedQueryCompilingExpressionVisitor + { + private class CustomShaperCompilingExpressionVisitor : ExpressionVisitor + { + private readonly bool _tracking; + + public CustomShaperCompilingExpressionVisitor(bool tracking) + { + _tracking = tracking; + } + + private static readonly MethodInfo _includeReferenceMethodInfo + = typeof(CustomShaperCompilingExpressionVisitor).GetTypeInfo() + .GetDeclaredMethod(nameof(IncludeReference)); + + private static void IncludeReference( + QueryContext queryContext, + TEntity entity, + TIncludedEntity relatedEntity, + INavigation navigation, + INavigation inverseNavigation, + Action fixup, + bool trackingQuery) + where TIncludingEntity : TEntity + { + if (entity is TIncludingEntity includingEntity) + { + if (trackingQuery) + { + // For non-null relatedEntity StateManager will set the flag + if (relatedEntity == null) + { + queryContext.StateManager.TryGetEntry(includingEntity).SetIsLoaded(navigation); + } + } + else + { + SetIsLoadedNoTracking(includingEntity, navigation); + if (relatedEntity != null) + { + fixup(includingEntity, relatedEntity); + if (inverseNavigation != null + && !inverseNavigation.IsCollection()) + { + SetIsLoadedNoTracking(relatedEntity, inverseNavigation); + } + } + } + } + } + + private static void SetIsLoadedNoTracking(object entity, INavigation navigation) + => ((ILazyLoader)(navigation + .DeclaringEntityType + .GetServiceProperties() + .FirstOrDefault(p => p.ClrType == typeof(ILazyLoader))) + ?.GetGetter().GetClrValue(entity)) + ?.SetLoaded(entity, navigation.Name); + + protected override Expression VisitExtension(Expression extensionExpression) + { + if (extensionExpression is IncludeExpression includeExpression) + { + Debug.Assert( + !includeExpression.Navigation.IsCollection(), + "Only reference include should be present in tree"); + + var entityClrType = includeExpression.EntityExpression.Type; + var includingClrType = includeExpression.Navigation.DeclaringEntityType.ClrType; + var inverseNavigation = includeExpression.Navigation.FindInverse(); + var relatedEntityClrType = includeExpression.Navigation.GetTargetType().ClrType; + if (includingClrType != entityClrType + && includingClrType.IsAssignableFrom(entityClrType)) + { + includingClrType = entityClrType; + } + + return Expression.Call( + _includeReferenceMethodInfo.MakeGenericMethod(entityClrType, includingClrType, relatedEntityClrType), + QueryCompilationContext.QueryContextParameter, + // We don't need to visit entityExpression since it is supposed to be a parameterExpression only + includeExpression.EntityExpression, + includeExpression.NavigationExpression, + Expression.Constant(includeExpression.Navigation), + Expression.Constant(inverseNavigation, typeof(INavigation)), + Expression.Constant( + GenerateFixup( + includingClrType, relatedEntityClrType, includeExpression.Navigation, inverseNavigation).Compile()), + Expression.Constant(_tracking)); + } + + return base.VisitExtension(extensionExpression); + } + + private static LambdaExpression GenerateFixup( + Type entityType, + Type relatedEntityType, + INavigation navigation, + INavigation inverseNavigation) + { + var entityParameter = Expression.Parameter(entityType); + var relatedEntityParameter = Expression.Parameter(relatedEntityType); + var expressions = new List + { + navigation.IsCollection() + ? AddToCollectionNavigation(entityParameter, relatedEntityParameter, navigation) + : AssignReferenceNavigation(entityParameter, relatedEntityParameter, navigation) + }; + + if (inverseNavigation != null) + { + expressions.Add( + inverseNavigation.IsCollection() + ? AddToCollectionNavigation(relatedEntityParameter, entityParameter, inverseNavigation) + : AssignReferenceNavigation(relatedEntityParameter, entityParameter, inverseNavigation)); + + } + + return Expression.Lambda(Expression.Block(typeof(void), expressions), entityParameter, relatedEntityParameter); + } + + private static Expression AssignReferenceNavigation( + ParameterExpression entity, + ParameterExpression relatedEntity, + INavigation navigation) + { + return entity.MakeMemberAccess(navigation.GetMemberInfo(forMaterialization: true, forSet: true)).Assign(relatedEntity); + } + + private static Expression AddToCollectionNavigation( + ParameterExpression entity, + ParameterExpression relatedEntity, + INavigation navigation) + => Expression.Call( + Expression.Constant(navigation.GetCollectionAccessor()), + _collectionAccessorAddMethodInfo, + entity, + relatedEntity, + Expression.Constant(true)); + + private static readonly MethodInfo _collectionAccessorAddMethodInfo + = typeof(IClrCollectionAccessor).GetTypeInfo() + .GetDeclaredMethod(nameof(IClrCollectionAccessor.Add)); + } + } +} diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryProjectionBindingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryProjectionBindingExpressionVisitor.cs index c3c4f7f11e8..ba40c75430c 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryProjectionBindingExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryProjectionBindingExpressionVisitor.cs @@ -167,6 +167,13 @@ protected override Expression VisitExtension(Expression extensionExpression) } } + if (extensionExpression is IncludeExpression includeExpression) + { + return _clientEval + ? base.VisitExtension(includeExpression) + : null; + } + throw new InvalidOperationException(); } diff --git a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryExpressionVisitor.cs index 7dfd50d02f1..cbfcfd82d2f 100644 --- a/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryExpressionVisitor.cs +++ b/src/EFCore.InMemory/Query/Internal/InMemoryShapedQueryExpressionVisitor.cs @@ -17,12 +17,10 @@ namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal { - public class InMemoryShapedQueryCompilingExpressionVisitor : ShapedQueryCompilingExpressionVisitor + public partial class InMemoryShapedQueryCompilingExpressionVisitor : ShapedQueryCompilingExpressionVisitor { private readonly Type _contextType; private readonly IDiagnosticsLogger _logger; - private static readonly ConstructorInfo _valueBufferConstructor - = typeof(ValueBuffer).GetConstructors().Single(ci => ci.GetParameters().Length == 1); public InMemoryShapedQueryCompilingExpressionVisitor( QueryCompilationContext queryCompilationContext, @@ -53,19 +51,20 @@ protected override Expression VisitExtension(Expression extensionExpression) protected override Expression VisitShapedQueryExpression(ShapedQueryExpression shapedQueryExpression) { - var shaperBody = InjectEntityMaterializers(shapedQueryExpression.ShaperExpression); + var inMemoryQueryExpression = (InMemoryQueryExpression)shapedQueryExpression.QueryExpression; - var innerEnumerable = Visit(shapedQueryExpression.QueryExpression); + var shaper = new ShaperExpressionProcessingExpressionVisitor(inMemoryQueryExpression) + .Inject(shapedQueryExpression.ShaperExpression); - var inMemoryQueryExpression = (InMemoryQueryExpression)shapedQueryExpression.QueryExpression; + shaper = InjectEntityMaterializers(shaper); - var newBody = new InMemoryProjectionBindingRemovingExpressionVisitor(inMemoryQueryExpression) - .Visit(shaperBody); + var innerEnumerable = Visit(inMemoryQueryExpression); - var shaperLambda = Expression.Lambda( - newBody, - QueryCompilationContext.QueryContextParameter, - inMemoryQueryExpression.ValueBufferParameter); + shaper = new InMemoryProjectionBindingRemovingExpressionVisitor(inMemoryQueryExpression).Visit(shaper); + + shaper = new CustomShaperCompilingExpressionVisitor(IsTracking).Visit(shaper); + + var shaperLambda = (LambdaExpression)shaper; return Expression.New( (IsAsync @@ -263,6 +262,7 @@ public ValueTask DisposeAsync() private class InMemoryProjectionBindingRemovingExpressionVisitor : ExpressionVisitor { private readonly InMemoryQueryExpression _queryExpression; + private readonly IDictionary> _materializationContextBindings = new Dictionary>(); @@ -284,7 +284,8 @@ protected override Expression VisitBinary(BinaryExpression binaryExpression) _materializationContextBindings[parameterExpression] = (IDictionary)GetProjectionIndex(projectionBindingExpression); - var updatedExpression = Expression.New(newExpression.Constructor, + var updatedExpression = Expression.New( + newExpression.Constructor, Expression.Constant(ValueBuffer.Empty), newExpression.Arguments[1]); @@ -300,7 +301,9 @@ protected override Expression VisitMethodCall(MethodCallExpression methodCallExp && methodCallExpression.Method.GetGenericMethodDefinition() == EntityMaterializerSource.TryReadValueMethod) { var property = (IProperty)((ConstantExpression)methodCallExpression.Arguments[2]).Value; - var indexMap = _materializationContextBindings[(ParameterExpression)((MethodCallExpression)methodCallExpression.Arguments[0]).Object]; + var indexMap = + _materializationContextBindings[ + (ParameterExpression)((MethodCallExpression)methodCallExpression.Arguments[0]).Object]; return Expression.Call( methodCallExpression.Method, diff --git a/src/EFCore.InMemory/Query/Internal/ShaperExpressionProcessingExpressionVisitor.cs b/src/EFCore.InMemory/Query/Internal/ShaperExpressionProcessingExpressionVisitor.cs new file mode 100644 index 00000000000..000bf5d72dc --- /dev/null +++ b/src/EFCore.InMemory/Query/Internal/ShaperExpressionProcessingExpressionVisitor.cs @@ -0,0 +1,101 @@ +// 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.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using Microsoft.EntityFrameworkCore.Query; + +namespace Microsoft.EntityFrameworkCore.InMemory.Query.Internal +{ + public class ShaperExpressionProcessingExpressionVisitor : ExpressionVisitor + { + private readonly InMemoryQueryExpression _queryExpression; + + private readonly IDictionary _mapping = new Dictionary(); + private readonly List _variables = new List(); + private readonly List _expressions = new List(); + + public ShaperExpressionProcessingExpressionVisitor( + InMemoryQueryExpression queryExpression) + { + _queryExpression = queryExpression; + } + + public virtual Expression Inject(Expression expression) + { + var result = Visit(expression); + + if (_expressions.All(e => e.NodeType == ExpressionType.Assign)) + { + result = new ReplacingExpressionVisitor(_expressions.Cast() + .ToDictionary(e => e.Left, e => e.Right)).Visit(result); + } + else + { + _expressions.Add(result); + result = Expression.Block(_variables, _expressions); + } + + return ConvertToLambda(result, Expression.Parameter(result.Type, "result")); + } + + private LambdaExpression ConvertToLambda(Expression result, ParameterExpression resultParameter) + => Expression.Lambda( + result, + QueryCompilationContext.QueryContextParameter, + _queryExpression.ValueBufferParameter); + + protected override Expression VisitExtension(Expression extensionExpression) + { + switch (extensionExpression) + { + case EntityShaperExpression entityShaperExpression: + { + var key = GenerateKey((ProjectionBindingExpression)entityShaperExpression.ValueBufferExpression); + if (!_mapping.TryGetValue(key, out var variable)) + { + variable = Expression.Parameter(entityShaperExpression.EntityType.ClrType); + _variables.Add(variable); + _expressions.Add(Expression.Assign(variable, entityShaperExpression)); + _mapping[key] = variable; + } + + return variable; + } + + case ProjectionBindingExpression projectionBindingExpression: + { + var key = GenerateKey(projectionBindingExpression); + if (!_mapping.TryGetValue(key, out var variable)) + { + variable = Expression.Parameter(projectionBindingExpression.Type); + _variables.Add(variable); + _expressions.Add(Expression.Assign(variable, projectionBindingExpression)); + _mapping[key] = variable; + } + + return variable; + } + + case IncludeExpression includeExpression: + { + var entity = Visit(includeExpression.EntityExpression); + _expressions.Add( + includeExpression.Update( + entity, + Visit(includeExpression.NavigationExpression))); + + return entity; + } + } + + return base.VisitExtension(extensionExpression); + } + + private Expression GenerateKey(ProjectionBindingExpression projectionBindingExpression) + => projectionBindingExpression.ProjectionMember != null + ? _queryExpression.GetMappedProjection(projectionBindingExpression.ProjectionMember) + : projectionBindingExpression; + } +} diff --git a/src/EFCore.Relational/Query/Internal/ShaperExpressionDedupingExpressionVisitor.cs b/src/EFCore.Relational/Query/Internal/ShaperExpressionProcessingExpressionVisitor.cs similarity index 100% rename from src/EFCore.Relational/Query/Internal/ShaperExpressionDedupingExpressionVisitor.cs rename to src/EFCore.Relational/Query/Internal/ShaperExpressionProcessingExpressionVisitor.cs diff --git a/test/EFCore.InMemory.FunctionalTests/InMemoryComplianceTest.cs b/test/EFCore.InMemory.FunctionalTests/InMemoryComplianceTest.cs index 854965f8126..110bc449f42 100644 --- a/test/EFCore.InMemory.FunctionalTests/InMemoryComplianceTest.cs +++ b/test/EFCore.InMemory.FunctionalTests/InMemoryComplianceTest.cs @@ -33,8 +33,6 @@ public class InMemoryComplianceTest : ComplianceTestBase typeof(ComplexNavigationsQueryTestBase<>), typeof(GearsOfWarQueryTestBase<>), typeof(IncludeAsyncTestBase<>), - typeof(IncludeOneToOneTestBase<>), - typeof(IncludeTestBase<>), typeof(InheritanceRelationshipsQueryTestBase<>), typeof(InheritanceTestBase<>), typeof(NullKeysTestBase<>), diff --git a/test/EFCore.InMemory.FunctionalTests/Query/IncludeInMemoryTest.cs b/test/EFCore.InMemory.FunctionalTests/Query/IncludeInMemoryTest.cs index 37110c22552..27889debacc 100644 --- a/test/EFCore.InMemory.FunctionalTests/Query/IncludeInMemoryTest.cs +++ b/test/EFCore.InMemory.FunctionalTests/Query/IncludeInMemoryTest.cs @@ -1,16 +1,492 @@ // 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 { - internal class IncludeInMemoryTest : IncludeTestBase + public class IncludeInMemoryTest : IncludeTestBase { public IncludeInMemoryTest(IncludeInMemoryFixture fixture, ITestOutputHelper testOutputHelper) : base(fixture) { //TestLoggerFactory.TestOutputHelper = testOutputHelper; } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_reference_and_collection_order_by(bool useString) + { + base.Include_reference_and_collection_order_by(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_references_then_include_collection(bool useString) + { + base.Include_references_then_include_collection(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Then_include_collection_order_by_collection_column(bool useString) + { + base.Then_include_collection_order_by_collection_column(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_when_result_operator(bool useString) + { + base.Include_when_result_operator(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection(bool useString) + { + base.Include_collection(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_then_reference(bool useString) + { + base.Include_collection_then_reference(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_with_last(bool useString) + { + base.Include_collection_with_last(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_with_last_no_orderby(bool useString) + { + base.Include_collection_with_last_no_orderby(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_skip_no_order_by(bool useString) + { + base.Include_collection_skip_no_order_by(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_take_no_order_by(bool useString) + { + base.Include_collection_take_no_order_by(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_skip_take_no_order_by(bool useString) + { + base.Include_collection_skip_take_no_order_by(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_alias_generation(bool useString) + { + base.Include_collection_alias_generation(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_and_reference(bool useString) + { + base.Include_collection_and_reference(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_as_no_tracking(bool useString) + { + base.Include_collection_as_no_tracking(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_as_no_tracking2(bool useString) + { + base.Include_collection_as_no_tracking2(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_dependent_already_tracked(bool useString) + { + base.Include_collection_dependent_already_tracked(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_dependent_already_tracked_as_no_tracking(bool useString) + { + base.Include_collection_dependent_already_tracked_as_no_tracking(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_on_additional_from_clause(bool useString) + { + base.Include_collection_on_additional_from_clause(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_on_additional_from_clause_no_tracking(bool useString) + { + base.Include_collection_on_additional_from_clause_no_tracking(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_on_additional_from_clause_with_filter(bool useString) + { + base.Include_collection_on_additional_from_clause_with_filter(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_on_additional_from_clause2(bool useString) + { + base.Include_collection_on_additional_from_clause2(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_on_join_clause_with_filter(bool useString) + { + base.Include_collection_on_join_clause_with_filter(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_on_join_clause_with_order_by_and_filter(bool useString) + { + base.Include_collection_on_join_clause_with_order_by_and_filter(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_on_group_join_clause_with_filter(bool useString) + { + base.Include_collection_on_group_join_clause_with_filter(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_on_inner_group_join_clause_with_filter(bool useString) + { + base.Include_collection_on_inner_group_join_clause_with_filter(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_when_groupby(bool useString) + { + base.Include_collection_when_groupby(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_when_groupby_subquery(bool useString) + { + base.Include_collection_when_groupby_subquery(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_order_by_collection_column(bool useString) + { + base.Include_collection_order_by_collection_column(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_order_by_key(bool useString) + { + base.Include_collection_order_by_key(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_order_by_non_key(bool useString) + { + base.Include_collection_order_by_non_key(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_order_by_non_key_with_take(bool useString) + { + base.Include_collection_order_by_non_key_with_take(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_order_by_non_key_with_skip(bool useString) + { + base.Include_collection_order_by_non_key_with_skip(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_order_by_non_key_with_first_or_default(bool useString) + { + base.Include_collection_order_by_non_key_with_first_or_default(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_order_by_subquery(bool useString) + { + base.Include_collection_order_by_subquery(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_principal_already_tracked(bool useString) + { + base.Include_collection_principal_already_tracked(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_principal_already_tracked_as_no_tracking(bool useString) + { + base.Include_collection_principal_already_tracked_as_no_tracking(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_single_or_default_no_result(bool useString) + { + base.Include_collection_single_or_default_no_result(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_when_projection(bool useString) + { + base.Include_collection_when_projection(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_with_filter(bool useString) + { + base.Include_collection_with_filter(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_with_filter_reordered(bool useString) + { + base.Include_collection_with_filter_reordered(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_duplicate_collection(bool useString) + { + base.Include_duplicate_collection(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_duplicate_collection_result_operator(bool useString) + { + base.Include_duplicate_collection_result_operator(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_duplicate_collection_result_operator2(bool useString) + { + base.Include_duplicate_collection_result_operator2(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_with_client_filter(bool useString) + { + base.Include_collection_with_client_filter(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_multi_level_reference_and_collection_predicate(bool useString) + { + base.Include_multi_level_reference_and_collection_predicate(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_multi_level_collection_and_then_include_reference_predicate(bool useString) + { + base.Include_multi_level_collection_and_then_include_reference_predicate(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_multiple_references_and_collection_multi_level(bool useString) + { + base.Include_multiple_references_and_collection_multi_level(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_multiple_references_and_collection_multi_level_reverse(bool useString) + { + base.Include_multiple_references_and_collection_multi_level_reverse(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_reference_and_collection(bool useString) + { + base.Include_reference_and_collection(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_force_alias_uniquefication(bool useString) + { + base.Include_collection_force_alias_uniquefication(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_references_and_collection_multi_level(bool useString) + { + base.Include_references_and_collection_multi_level(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_then_include_collection(bool useString) + { + base.Include_collection_then_include_collection(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_then_include_collection_then_include_reference(bool useString) + { + base.Include_collection_then_include_collection_then_include_reference(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_then_include_collection_predicate(bool useString) + { + base.Include_collection_then_include_collection_predicate(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_references_and_collection_multi_level_predicate(bool useString) + { + base.Include_references_and_collection_multi_level_predicate(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_multi_level_reference_then_include_collection_predicate(bool useString) + { + base.Include_multi_level_reference_then_include_collection_predicate(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_multiple_references_then_include_collection_multi_level(bool useString) + { + base.Include_multiple_references_then_include_collection_multi_level(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_multiple_references_then_include_collection_multi_level_reverse(bool useString) + { + base.Include_multiple_references_then_include_collection_multi_level_reverse(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_references_then_include_collection_multi_level(bool useString) + { + base.Include_references_then_include_collection_multi_level(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_references_then_include_collection_multi_level_predicate(bool useString) + { + base.Include_references_then_include_collection_multi_level_predicate(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_with_conditional_order_by(bool useString) + { + base.Include_collection_with_conditional_order_by(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_GroupBy_Select(bool useString) + { + base.Include_collection_GroupBy_Select(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_Join_GroupBy_Select(bool useString) + { + base.Include_collection_Join_GroupBy_Select(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Join_Include_collection_GroupBy_Select(bool useString) + { + base.Join_Include_collection_GroupBy_Select(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_GroupJoin_GroupBy_Select(bool useString) + { + base.Include_collection_GroupJoin_GroupBy_Select(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void GroupJoin_Include_collection_GroupBy_Select(bool useString) + { + base.GroupJoin_Include_collection_GroupBy_Select(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_SelectMany_GroupBy_Select(bool useString) + { + base.Include_collection_SelectMany_GroupBy_Select(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void SelectMany_Include_collection_GroupBy_Select(bool useString) + { + base.SelectMany_Include_collection_GroupBy_Select(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_distinct_is_server_evaluated(bool useString) + { + base.Include_collection_distinct_is_server_evaluated(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_OrderBy_object(bool useString) + { + base.Include_collection_OrderBy_object(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_OrderBy_empty_list_contains(bool useString) + { + base.Include_collection_OrderBy_empty_list_contains(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_OrderBy_empty_list_does_not_contains(bool useString) + { + base.Include_collection_OrderBy_empty_list_does_not_contains(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_OrderBy_list_contains(bool useString) + { + base.Include_collection_OrderBy_list_contains(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_collection_OrderBy_list_does_not_contains(bool useString) + { + base.Include_collection_OrderBy_list_does_not_contains(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override Task Include_empty_collection_sets_IsLoaded(bool useString, bool async) + { + return base.Include_empty_collection_sets_IsLoaded(useString, async); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_closes_reader(bool useString) + { + base.Include_closes_reader(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_with_take(bool useString) + { + base.Include_with_take(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_with_skip(bool useString) + { + base.Include_with_skip(useString); + } + + [ConditionalTheory(Skip = "issue #16963")] + public override void Include_list(bool useString) + { + base.Include_list(useString); + } } } diff --git a/test/EFCore.InMemory.FunctionalTests/Query/IncludeOneToOneInMemoryTest.cs b/test/EFCore.InMemory.FunctionalTests/Query/IncludeOneToOneInMemoryTest.cs index 377ba064a86..71cb7973490 100644 --- a/test/EFCore.InMemory.FunctionalTests/Query/IncludeOneToOneInMemoryTest.cs +++ b/test/EFCore.InMemory.FunctionalTests/Query/IncludeOneToOneInMemoryTest.cs @@ -5,7 +5,7 @@ namespace Microsoft.EntityFrameworkCore.Query { - internal class IncludeOneToOneInMemoryTest : IncludeOneToOneTestBase + public class IncludeOneToOneInMemoryTest : IncludeOneToOneTestBase { public IncludeOneToOneInMemoryTest(OneToOneQueryInMemoryFixture fixture) : base(fixture)