Fix IIdentityResolutionInterceptor not called when entity returned from multiple queries#37786
Draft
Fix IIdentityResolutionInterceptor not called when entity returned from multiple queries#37786
Conversation
Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
… detection Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Copilot
AI
changed the title
[WIP] Fix IIdentityResolutionInterceptor not intercepting resolutions
Fix IIdentityResolutionInterceptor not called when entity returned from multiple queries
Feb 24, 2026
src/EFCore/Query/QueryContext.cs
Outdated
| /// doing so can result in application failures when updating to a new Entity Framework Core release. | ||
| /// </summary> | ||
| [EntityFrameworkInternal] | ||
| public virtual bool HasResolutionInterceptor |
Member
There was a problem hiding this comment.
@copilot Find another way to fix this without adding a property to QueryContext. Be creative and explore several posibilities
Contributor
Author
There was a problem hiding this comment.
Addressed in e81c8cb. Instead of adding a property to QueryContext, I modified TryGetEntry to return null when _stateManager.HasResolutionInterceptor is true and the existing entry is Unchanged. This causes the shaper to take the materialize path, which calls StartTrackingFromQuery, which invokes the interceptor. No public property is added to QueryContext, and ShapedQueryCompilingExpressionVisitor no longer needs any new members.
…try when interceptor present Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
IIdentityResolutionInterceptor.UpdateTrackedInstancewas never invoked when a tracked entity was returned by a subsequent query. The generated shaper code short-circuited viaTryGetEntry(key, keyValues)and returned the existing tracked entity directly, bypassingStartTrackingFromQueryentirely.Changes
QueryContext.TryGetEntry: Modified to returnnullwhenHasResolutionInterceptoris true and the existing entry isUnchanged. This forces the shaper's materialize path, which callsStartTrackingFromQuery, which in turn invokes the interceptor. No public property is added toQueryContext.StateManager.StartTrackingFromQuery: Added key-conflict detection: when a newly materialized entity shares a key with an already-tracked entry, calls the interceptor if the existing entry is Unchanged. Skips the interceptor forModified/Deleted/Addedentries to preserve in-memory user modifications (e.g., during lazy loads).ShapedQueryCompilingExpressionVisitor: Added reset ofinstanceVariable = entry.EntityafterStartTrackinginMaterializeEntityso the correct (existing) entity is returned to the caller when the interceptor resolves to an already-tracked instance.IStateManager/StateManager: AddedHasResolutionInterceptorproperty used internally byQueryContext.TryGetEntryto detect whether an interceptor is registered.Example
Original prompt
🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.