-
Notifications
You must be signed in to change notification settings - Fork 3.3k
Complex json change tracking #36446
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
Complex json change tracking #36446
Conversation
Visit(relationalGroupByResultExpression.KeyIdentifier), | ||
QueryCompilationContext.QueryContextParameter, | ||
_dataReaderParameter); | ||
try |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just indented the code to add the management of _parentVisitor._currentShaperProcessor
.
|
||
relationalCommandResolver = _parentVisitor.CreateRelationalCommandResolverExpression(_selectExpression); | ||
readerColumns = _readerColumns; | ||
relatedDataLoaders = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As above, only indentation change.
test/EFCore.SqlServer.FunctionalTests/Update/ComplexCollectionJsonUpdateSqlServerTest.cs
Show resolved
Hide resolved
73d2e74
to
4b9bc54
Compare
Name: 'Test Company' | ||
Contacts (Complex: List<Contact>) | ||
Department (Complex: Department) | ||
Budget: 10000.00 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This failed on SQLite because we get Budget: 10000.0
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add something like Assert.DoesNotContain("Exception");
...l/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs
Outdated
Show resolved
Hide resolved
4b9bc54
to
6cf70ef
Compare
With JSON owned entities, the root (non-JSON) entity is materialized and tracked, and then JSON shaper code materializes the JSON owned entity and tracks that separately; the change tracker does the fix-up etc. When originally implementing the shaper support for complex JSON, I also added JSON shaper code after materialization - similar to the owned flow - but that's too late, since StartTracking already gets called as part of materiailzation.
I considered separating StartTracking from materialization and pulling the former up, so that I can inject JSON shaper code in between - but that's quite a significant change would probably break external (non-relational) providers. Instead I opted for adding an extension hook during materialization, that gets called after the structural type is instantiated and its regular properties are populated, but before it's handed off to StartTracking().
Adding such a hook proved difficult - our shaper generation really isn't designed with extensibility in mind. The most problematic is that in relational, ShapedQueryCompilingExpressionVisitor immediately calls a separate private visitor - ShaperProcessingExpressionVisitor - which does most of the work, and occasionally calls into the "parent" ShaperProcessingExpressionVisitor. One of these calls is for structural type materialization, making it difficult to have the extension hook call back into ShaperProcessingExpressionVisitor, which is where the JSON shaper logic lives (and it relies on various global state inside that visitor, and so can't easily be moved out). So I ended up tracking the current ShaperProcessingExpressionVisitor on RelationalShapedQueryCompilingExpressionVisitor, so that the hook can call into it; and since ShaperProcessingExpressionVisitor instantiates and calls itself recursively, that also needs to be accounted for.
There's a lot of potential for simplifying and cleaning everything up here, I hope we get to it at some point.
/cc @artl93