-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
Proxy Change Detection #19437
Proxy Change Detection #19437
Conversation
…-organized to separate change detection, lazy loading, and common proxy functionality tests. Still need to write change detection tests.
Accidental OR instead of AND.
…ifyCollectionChanged events on collection properties can bubble up when necessary.
src/EFCore.Proxies/Proxies/Internal/PropertyChangedInterceptor.cs
Outdated
Show resolved
Hide resolved
src/EFCore.Proxies/Proxies/Internal/PropertyChangingInterceptor.cs
Outdated
Show resolved
Hide resolved
@orionstudt I made a pass through and generally this looks great. I will do another review when I am properly back at work in the new year. Your specific questions here:
|
@ajcvickers Awesome. Some thoughts:
Sounds good to me. I will add that check on my next run through.
Also sounds good. Makes that a bit easier. I'll have to see if I can find the code for the error you mentioned. It's occurring to me that this is also not specific to navigations since owned types can also be collections, and may get interesting with the indexer properties that I noticed you guys are working on.
Any thoughts on which of the 3 strategies we should default to? Enjoy your time off, and happy new year. |
@orionstudt The existing error is https://github.com/aspnet/EntityFrameworkCore/blob/b36ea0a3b7dc4aef662d7b2ead8fbce3b6b50d85/src/EFCore/Properties/CoreStrings.resx#L204 The strategy should be |
…ully, need to decide how to handle ChangeTrackingStrategy validation.
@ajcvickers So I've been working on defaulting to I'm setting the default I tried having a separate convention that runs after It also doesn't look like the proxies lib, not being a database provider, should do any overloading of Thoughts on how to get around that? |
… implementation, change detection proxy tests written, constructor binding set. Need to figure out how to fix ChangeTracker subscribing on Add before proxied.
Disregard previous comment, I slept on it. Came up with a solution by mimicking the Annotation used in the Tests are now written, everything looks kosher. Only issue is that when you add an entity to the context the first thing it tries to do is start tracking that entity. The problem is consumers obviously are providing the CLR type so the entity hasn't been proxied and doesn't have the INPC interfaces yet... |
@orionstudt Making great progress here! With regard to integration with model validation, I think it would be better to do something a bit more robust. I will look into this a bit more and discuss with @AndriySvyryd. I think ideally the extension should be able to:
This is closely related to your about what should happen if the application directly creates an entity instance an then attempts to track it. In EF6, effective use of notification entities was hampered by supporting mixed graphs where some entities are proxies and some are not. For example, entity snapshots and DetectChanges might still be needed. In addition, it was confusing when people accidentally didn't create proxy instances and then didn't get the behavior they were expecting. This is why EF Core is a lot more strict about actually using notification entities if they have been configured--hence the validation discussed above. Based on this we should not allow a non-proxy instance to be tracked. (This might just mean updating the current exception message.) On the other hand, forcing proxy instances to be used can be a burden to the application since any place that needs to create an entity instance needs to do so directly or indirectly using EF Core. I'm leaning towards requiring proxy instance, but I'll also discuss this with the team. One final thing: Take a look at |
…er in the pipeline and doesn't overwrite a strategy set at the entity level.
@ajcvickers Awesome. Glad you responded because I went down a little rabbit hole, lol. I got it to a point where it was using I'll take a look at those tests next time I get a chance and see if I can get more variation in there. |
@orionstudt After discussion with the team:
|
…d some more variation to the testing.
…g enabled. Wrote a test to check for a navigational property being marked modified before it is loaded.
@ajcvickers So I added a test to check for your "setting a navigation property to null before it is included / lazy loaded" scenario. We can get it to snapshot and raise when |
@orionstudt See my comment here with regard to the model validation: #15660 (comment) I expect that we will not block this PR waiting for a solution to that issue, but let me discuss with the team tomorrow. With regard to the setting a null navigation to null scenario, I think we can break that out into a separate issue--maybe I will just re-open the original one. Then we should fix that issue so that it works consistently either with proxies or manually implemented notification entities. |
@ajcvickers Cool. Sounds like we'll have it all split out into separate issues then - so this PR is about ready for review. I will backtrack the null navigation test so that we are passing and then flag this ready. Let me know if you think the existing tests need to be any more robust than they are. |
@orionstudt Thanks for this high quality PR and for collaborating well on working through the issues. Much appreciated. |
Thanks @ajcvickers ! It's been a pleasure. |
Squashed commit: * initial proxy change detection commit. Building and tests slightly re-organized to separate change detection, lazy loading, and common proxy functionality tests. Still need to write change detection tests. * Fix debug log fragment mistake. Accidental OR instead of AND. * Add observable collection check to PropertyChangedInterceptor so INotifyCollectionChanged events on collection properties can bubble up when necessary. * Existing tests now passing, ProxyFactory resolving extension successfully, need to decide how to handle ChangeTrackingStrategy validation. * Change tracking strategy validation bypassed mimicking ChangeDetector implementation, change detection proxy tests written, constructor binding set. Need to figure out how to fix ChangeTracker subscribing on Add before proxied. * Resolve potential null ref exception. * Modify change tracking strategy default convention so it occurs earlier in the pipeline and doesn't overwrite a strategy set at the entity level. * Update existing tests to use proxies from the start. Still need to add some more variation to the testing. * Added slight variation to tests to account for lazy loading also being enabled. Wrote a test to check for a navigational property being marked modified before it is loaded. * Remove "non-loaded (null) navigation set to null" test.
Addresses #10949
This was getting a bit bigger than I originally anticipated so making a draft pull request for any early feedback.
Note that the tests are currently all in
LazyLoadingProxyTests
and as part of this PR I have split them out into 3 files (change detection, lazy loading, proxy) since they don't all fall under "Lazy-Loading" anymore. All the tests still exist in their current form. Hopefully that's not an issue.Things that still need to be done:
Some questions copied from #10949, which still stand:
If the entity already implements one of the notify interfaces, should we just not proxy that interface and leave it up to the consumer to raise those events? Edit: alternatively we could just continue to proxy and potentially raise 2 events if the consumer is already raising 1. Currently I am not even checking for this. At the moment I don't think this will be an issue, but could and probably will make tests against entities that are already implementing these interfaces in order to verify.
In a similar vein, for collection navigations we can bubble a collection change up to the parent entity if the underlying collection is one of the observable collection types. But it will be up to the consumer to instantiate that collection as one of the observable types in their entity's constructor, is that ok?
With what I've currently written out, if a consumer enables
UseChangeDetectionProxies
the defaultChangeDetectionStrategy
will still beSnapshot
so none of the entities will receive the INPC proxies. Should we also be updating theChangeDetectionStrategy
to some other default value when change detection proxies are first enabled?Current issue that I wouldn't mind insight on:
IProxyFactory now relies on ProxiesOptionsExtension in order to determine how to proxy entities. Since IProxyFactory is registered as a "provider-specific service" it is apparently not able to resolve IDbContextOptions to retrieve the extension. Is there some existing mechanism for a "provider-specific service" to get access to an extension? I couldn't seem to find one.Edit: looking at it again and the IProxyFactory.Create takes in DbContext - so I'm just realizing that IProxyFactory is not tied to a DbContext (whoops). Will either need to change that or have other methods provide DbContext when necessary...