Skip to content

Commit

Permalink
Updated to handle case where same navigation is included twice, the f…
Browse files Browse the repository at this point in the history
…irst time with setLoaded = false.
  • Loading branch information
ajcvickers committed Dec 7, 2020
1 parent 09a1bf2 commit e623114
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,17 @@ public IncludeTreeNode(IEntityType entityType, EntityReference entityReference,

public IEntityType EntityType { get; }
public LambdaExpression FilterExpression { get; private set; }

public bool SetLoaded { get; }
public bool SetLoaded { get; private set; }

public IncludeTreeNode AddNavigation(INavigationBase navigation, bool setLoaded)
{
if (TryGetValue(navigation, out var existingValue))
{
if (setLoaded && !existingValue.SetLoaded)
{
existingValue.SetLoaded = true;
}

return existingValue;
}

Expand Down
78 changes: 78 additions & 0 deletions test/EFCore.Specification.Tests/ManyToManyLoadTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -819,6 +819,84 @@ public virtual async Task Load_collection_using_Query_with_Include(bool async)
Assert.Equal(21, context.ChangeTracker.Entries().Count());
}

[ConditionalTheory]
[InlineData(true)]
[InlineData(false)]
public virtual async Task Load_collection_using_Query_with_Include_for_inverse(bool async)
{
using var context = Fixture.CreateContext();

var left = context.Set<EntityOne>().Find(3);

ClearLog();

var collectionEntry = context.Entry(left).Collection(e => e.TwoSkipShared);

Assert.False(collectionEntry.IsLoaded);

var queryable = collectionEntry.Query().Include(e => e.OneSkipShared);
var children = async
? await queryable.ToListAsync()
: queryable.ToList();

Assert.False(collectionEntry.IsLoaded);
foreach (var entityTwo in left.TwoSkipShared)
{
Assert.True(context.Entry(entityTwo).Collection(e => e.OneSkipShared).IsLoaded);
}

RecordLog();
context.ChangeTracker.LazyLoadingEnabled = false;

Assert.Equal(3, left.TwoSkipShared.Count);
foreach (var right in left.TwoSkipShared)
{
Assert.Contains(left, right.OneSkipShared);
}

Assert.Equal(children, left.TwoSkipShared.ToList());
Assert.Equal(7, context.ChangeTracker.Entries().Count());
}

[ConditionalTheory]
[InlineData(true)]
[InlineData(false)]
public virtual async Task Load_collection_using_Query_with_Include_for_same_collection(bool async)
{
using var context = Fixture.CreateContext();

var left = context.Set<EntityOne>().Find(3);

ClearLog();

var collectionEntry = context.Entry(left).Collection(e => e.TwoSkipShared);

Assert.False(collectionEntry.IsLoaded);

var queryable = collectionEntry.Query().Include(e => e.OneSkipShared).ThenInclude(e => e.TwoSkipShared);
var children = async
? await queryable.ToListAsync()
: queryable.ToList();

Assert.True(collectionEntry.IsLoaded);
foreach (var entityTwo in left.TwoSkipShared)
{
Assert.True(context.Entry(entityTwo).Collection(e => e.OneSkipShared).IsLoaded);
}

RecordLog();
context.ChangeTracker.LazyLoadingEnabled = false;

Assert.Equal(3, left.TwoSkipShared.Count);
foreach (var right in left.TwoSkipShared)
{
Assert.Contains(left, right.OneSkipShared);
}

Assert.Equal(children, left.TwoSkipShared.ToList());
Assert.Equal(7, context.ChangeTracker.Entries().Count());
}

[ConditionalTheory]
[InlineData(true)]
[InlineData(false)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,59 @@ FROM [JoinOneToTwo] AS [j0]
}


public override async Task Load_collection_using_Query_with_Include_for_inverse(bool async)
{
await base.Load_collection_using_Query_with_Include_for_inverse(async);

AssertSql(
@"@__p_0='3'
SELECT [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId], [e].[Id], [t].[EntityOneId], [t].[EntityTwoId], [t0].[EntityOneId], [t0].[EntityTwoId], [t0].[Id], [t0].[Name]
FROM [EntityOnes] AS [e]
INNER JOIN (
SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[Name], [e1].[ReferenceInverseId], [e0].[EntityOneId], [e0].[EntityTwoId]
FROM [EntityOneEntityTwo] AS [e0]
INNER JOIN [EntityTwos] AS [e1] ON [e0].[EntityTwoId] = [e1].[Id]
) AS [t] ON [e].[Id] = [t].[EntityOneId]
LEFT JOIN (
SELECT [e2].[EntityOneId], [e2].[EntityTwoId], [e3].[Id], [e3].[Name]
FROM [EntityOneEntityTwo] AS [e2]
INNER JOIN [EntityOnes] AS [e3] ON [e2].[EntityOneId] = [e3].[Id]
WHERE [e3].[Id] = @__p_0
) AS [t0] ON [t].[Id] = [t0].[EntityTwoId]
WHERE [e].[Id] = @__p_0
ORDER BY [e].[Id], [t].[EntityOneId], [t].[EntityTwoId], [t].[Id], [t0].[EntityOneId], [t0].[EntityTwoId], [t0].[Id]");
}

public override async Task Load_collection_using_Query_with_Include_for_same_collection(bool async)
{
await base.Load_collection_using_Query_with_Include_for_same_collection(async);

AssertSql(
@"@__p_0='3'
SELECT [t].[Id], [t].[CollectionInverseId], [t].[Name], [t].[ReferenceInverseId], [e].[Id], [t].[EntityOneId], [t].[EntityTwoId], [t1].[EntityOneId], [t1].[EntityTwoId], [t1].[Id], [t1].[Name], [t1].[EntityOneId0], [t1].[EntityTwoId0], [t1].[Id0], [t1].[CollectionInverseId], [t1].[Name0], [t1].[ReferenceInverseId]
FROM [EntityOnes] AS [e]
INNER JOIN (
SELECT [e1].[Id], [e1].[CollectionInverseId], [e1].[Name], [e1].[ReferenceInverseId], [e0].[EntityOneId], [e0].[EntityTwoId]
FROM [EntityOneEntityTwo] AS [e0]
INNER JOIN [EntityTwos] AS [e1] ON [e0].[EntityTwoId] = [e1].[Id]
) AS [t] ON [e].[Id] = [t].[EntityOneId]
LEFT JOIN (
SELECT [e2].[EntityOneId], [e2].[EntityTwoId], [e3].[Id], [e3].[Name], [t0].[EntityOneId] AS [EntityOneId0], [t0].[EntityTwoId] AS [EntityTwoId0], [t0].[Id] AS [Id0], [t0].[CollectionInverseId], [t0].[Name] AS [Name0], [t0].[ReferenceInverseId]
FROM [EntityOneEntityTwo] AS [e2]
INNER JOIN [EntityOnes] AS [e3] ON [e2].[EntityOneId] = [e3].[Id]
LEFT JOIN (
SELECT [e4].[EntityOneId], [e4].[EntityTwoId], [e5].[Id], [e5].[CollectionInverseId], [e5].[Name], [e5].[ReferenceInverseId]
FROM [EntityOneEntityTwo] AS [e4]
INNER JOIN [EntityTwos] AS [e5] ON [e4].[EntityTwoId] = [e5].[Id]
) AS [t0] ON [e3].[Id] = [t0].[EntityOneId]
WHERE [e3].[Id] = @__p_0
) AS [t1] ON [t].[Id] = [t1].[EntityTwoId]
WHERE [e].[Id] = @__p_0
ORDER BY [e].[Id], [t].[EntityOneId], [t].[EntityTwoId], [t].[Id], [t1].[EntityOneId], [t1].[EntityTwoId], [t1].[Id], [t1].[EntityOneId0], [t1].[EntityTwoId0], [t1].[Id0]");
}

public override async Task Load_collection_using_Query_with_Include(bool async)
{
await base.Load_collection_using_Query_with_Include(async);
Expand Down

0 comments on commit e623114

Please sign in to comment.