Skip to content

Commit

Permalink
Query: Bring back join entity when including Skip collection navigati…
Browse files Browse the repository at this point in the history
…on in tracking query (#21504)

Also applicable for no tracking query with identity resolution

Part of #19003
  • Loading branch information
smitpatel committed Jul 3, 2020
1 parent cb3f820 commit 98ede46
Show file tree
Hide file tree
Showing 16 changed files with 2,099 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -463,14 +463,17 @@ outerKey is NewArrayExpression newArrayExpression
/// </summary>
private sealed class IncludeExpandingExpressionVisitor : ExpandingExpressionVisitor
{
private readonly bool _allowCycles;
private static readonly MethodInfo _fetchJoinEntityMethodInfo =
typeof(IncludeExpandingExpressionVisitor).GetTypeInfo().GetDeclaredMethod(nameof(FetchJoinEntity));

private readonly bool _queryStateManager;

public IncludeExpandingExpressionVisitor(
NavigationExpandingExpressionVisitor navigationExpandingExpressionVisitor,
NavigationExpansionExpression source)
: base(navigationExpandingExpressionVisitor, source)
{
_allowCycles = navigationExpandingExpressionVisitor._queryCompilationContext.QueryTrackingBehavior == QueryTrackingBehavior.TrackAll
_queryStateManager = navigationExpandingExpressionVisitor._queryCompilationContext.QueryTrackingBehavior == QueryTrackingBehavior.TrackAll
|| navigationExpandingExpressionVisitor._queryCompilationContext.QueryTrackingBehavior == QueryTrackingBehavior.NoTrackingWithIdentityResolution;
}

Expand Down Expand Up @@ -626,7 +629,7 @@ private bool ReconstructAnonymousType(Expression currentRoot, NewExpression newE

private Expression ExpandInclude(Expression root, EntityReference entityReference)
{
if (!_allowCycles)
if (!_queryStateManager)
{
VerifyNoCycles(entityReference.IncludePaths);
}
Expand Down Expand Up @@ -673,6 +676,32 @@ private Expression ExpandIncludesHelper(Expression root, EntityReference entityR
_ => throw new InvalidOperationException(CoreStrings.UnhandledNavigationBase(navigationBase.GetType()))
};

if (_queryStateManager
&& navigationBase is ISkipNavigation
&& included is MaterializeCollectionNavigationExpression materializeCollectionNavigationExpression
&& materializeCollectionNavigationExpression.Subquery is MethodCallExpression joinMethodCallExpression
&& joinMethodCallExpression.Method.IsGenericMethod
&& joinMethodCallExpression.Method.GetGenericMethodDefinition() == QueryableMethods.Join
&& joinMethodCallExpression.Arguments[4] is UnaryExpression unaryExpression
&& unaryExpression.NodeType == ExpressionType.Quote
&& unaryExpression.Operand is LambdaExpression resultSelectorLambda
&& resultSelectorLambda.Body == resultSelectorLambda.Parameters[1])
{
var joinParameter = resultSelectorLambda.Parameters[0];
var targetParameter = resultSelectorLambda.Parameters[1];
var newResultSelector = Expression.Quote(
Expression.Lambda(
Expression.Call(
_fetchJoinEntityMethodInfo.MakeGenericMethod(joinParameter.Type, targetParameter.Type),
joinParameter,
targetParameter),
joinParameter,
targetParameter));

included = materializeCollectionNavigationExpression.Update(
joinMethodCallExpression.Update(null, joinMethodCallExpression.Arguments.Take(4).Append(newResultSelector)));
}

// Collection will expand it's includes when reducing the navigationExpansionExpression
if (!navigationBase.IsCollection)
{
Expand Down Expand Up @@ -700,6 +729,8 @@ private Expression ExpandIncludesHelper(Expression root, EntityReference entityR

return result;
}

private static TTarget FetchJoinEntity<TJoin, TTarget>(TJoin joinEntity, TTarget targetEntity) => targetEntity;
}

/// <summary>
Expand Down
2 changes: 1 addition & 1 deletion test/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
</PropertyGroup>

<PropertyGroup>
<NoWarn>$(NoWarn);1591;xUnit1003;xUnit1004;xUnit1010;xUnit1013</NoWarn>
<NoWarn>$(NoWarn);1591;xUnit1000;xUnit1003;xUnit1004;xUnit1010;xUnit1013</NoWarn>
</PropertyGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ public class InMemoryComplianceTest : ComplianceTestBase
typeof(FunkyDataQueryTestBase<>),
typeof(OptimisticConcurrencyTestBase<>),
typeof(StoreGeneratedTestBase<>),
typeof(ConferencePlannerTestBase<>)
typeof(ConferencePlannerTestBase<>),
typeof(ManyToManyQueryTestBase<>),
};

protected override Assembly TargetAssembly { get; } = typeof(InMemoryComplianceTest).Assembly;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// 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 Xunit.Abstractions;

namespace Microsoft.EntityFrameworkCore.Query
{
public class ManyToManyNoTrackingQueryInMemoryTest : ManyToManyNoTrackingQueryTestBase<ManyToManyQueryInMemoryFixture>
{
public ManyToManyNoTrackingQueryInMemoryTest(ManyToManyQueryInMemoryFixture fixture, ITestOutputHelper testOutputHelper)
: base(fixture)
{
//TestLoggerFactory.TestOutputHelper = testOutputHelper;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace Microsoft.EntityFrameworkCore.Query
{
public class ManyToManyQueryInMemoryTest : ManyToManyQueryTestBase<ManyToManyQueryInMemoryFixture>
internal class ManyToManyQueryInMemoryTest : ManyToManyQueryTestBase<ManyToManyQueryInMemoryFixture>
{
public ManyToManyQueryInMemoryTest(ManyToManyQueryInMemoryFixture fixture, ITestOutputHelper testOutputHelper)
: base(fixture)
Expand Down
Loading

0 comments on commit 98ede46

Please sign in to comment.