Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[5.0.2] Stop marking the inverse navigation as loaded when loading a many-to-many navigation #23589

Merged
merged 3 commits into from
Dec 11, 2020

Conversation

ajcvickers
Copy link
Contributor

@ajcvickers ajcvickers commented Dec 4, 2020

Fixes #23475

This is a targeted patch fix which special cases many-to-many loading. I will file an issue for a more general solution using an appropriate general update to query. See #22022.

Description

This is a bug in many-to-many relationships, a major new feature in EF Core 5.0. When loading a collection navigation property, the inverse navigation property is marked as loaded. This is not correct, since only entities related to the source entity are loaded. This means that attempting to load the inverse is a no-op because it is already marked as loaded, and hence data is missing in the context.

Customer Impact

Related entities are not loaded from the database when they should be, leading to possible data corruption in an application that assumes this is working correctly. This will kind of problem is often hard to find since there is no error, just incorrect data.

How found

Customer reported on 5.0.0.

Test coverage

We did not have test coverage for this case. However, this isn't why we didn't catch this, since I didn't think about the consequences for the IsLoaded flag here, and only investigation of this issue made me realize the mistake. We have added more test coverage in this PR.

Regression?

No; new feature in 5.0.

Risk

Medium. The underlying problem is that we ere using Include in the generated query to do lazy loading. The behavior of Include is to set the collection as loaded, even if filtered, which means we can't change the default behavior of Include. Therefore, we have introduced a new internal NotQuiteInclude method that is processed the same as Include in the query pipeline, but then changes the final materialization delegate to indicate that the collection should not be loaded. This is new code path has been done in a way that it is only used for this case, and can be disabled with a quirk switch. It has also been reviewed in detail by the team and we have added more testing.

@ajcvickers ajcvickers requested review from smitpatel and a team December 4, 2020 22:33
@ajcvickers ajcvickers changed the title Stop marking the inverse navigation as loaded when loading a many-to-many navigation [5.0.2] Stop marking the inverse navigation as loaded when loading a many-to-many navigation Dec 4, 2020
@ajcvickers ajcvickers added this to the 5.0.x milestone Dec 4, 2020
@smitpatel
Copy link
Contributor

Add some additional tests around using context.Entry(e).Collection(e => e.SkipNavigation) queryable with other includes/filtered-include/join/projection-removing-entity-from-result.

@ajcvickers
Copy link
Contributor Author

@smitpatel Updated and added new tests.

@ajcvickers ajcvickers requested a review from smitpatel December 6, 2020 00:33
@ajcvickers ajcvickers requested a review from smitpatel December 7, 2020 20:01
@ajcvickers
Copy link
Contributor Author

@dotnet/efteam Given the risk, I would appreciate some additional reviews on this. In particular, from @maumar, but also from anyone else. Look for cases where this change may impact other queries, such as the cases that Smit has previously called out.

@ajcvickers
Copy link
Contributor Author

Approved by Tactics for 5.0.2. Please wait for the branch to open before merging.

@ajcvickers ajcvickers removed the blocked label Dec 8, 2020
@maumar
Copy link
Contributor

maumar commented Dec 9, 2020

@ajcvickers you could also add test that uses query with Include/FilteredInclude directly and make sure that the other side is not being loaded.

…many navigation

Fixes #23475

This is a targeted patch fix which special cases many-to-many loading. I will file an issue for a more general solution using an appropriate general update to query.
@ajcvickers ajcvickers force-pushed the LoadedBakedPotatoSkips1130 branch from e623114 to 45d27f2 Compare December 11, 2020 16:47
@ajcvickers ajcvickers merged commit 45d27f2 into release/5.0 Dec 11, 2020
@ajcvickers ajcvickers deleted the LoadedBakedPotatoSkips1130 branch December 11, 2020 16:52
@ajcvickers ajcvickers removed this from the 5.0.2 milestone Dec 11, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants