Implement partial property loading in relational query#37857
Implement partial property loading in relational query#37857roji merged 1 commit intodotnet:mainfrom
Conversation
eb525c8 to
f768fbc
Compare
There was a problem hiding this comment.
Pull request overview
This PR implements partial property loading for the relational query pipeline (#37279), the first step toward supporting "stop loading vector properties" optimization. Non-auto-loaded properties (those with IsAutoLoaded = false) are now excluded from SQL SELECT projections and properly handled during materialization and change tracking. The primary use case is SQL Server vector properties (SqlVector<T>), which should not be fetched by default as they can be large.
Changes:
- Non-auto-loaded properties are excluded from SQL entity projections and post-construction materialization; shadow properties get their sentinel value instead of a value buffer read.
- A model validator is added to prevent constructor-bound properties from being configured as non-auto-loaded.
- The
SqlServerAutoLoadConventionis fixed to also handle nullable vector types (SqlVector<float>?) by callingUnwrapNullableType()before checking for theSqlVector<>open generic.
Reviewed changes
Copilot reviewed 12 out of 13 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs |
Skips non-auto-loaded properties when building the entity projection into the SELECT list |
src/EFCore/Query/Internal/StructuralTypeMaterializerSource.cs |
Excludes non-auto-loaded properties from the set of properties assigned after construction |
src/EFCore/Query/ShapedQueryCompilingExpressionVisitor.cs |
Uses sentinel value for non-auto-loaded shadow properties instead of reading from value buffer |
src/EFCore/Infrastructure/ModelValidator.cs |
Adds validation that constructor-bound properties cannot be non-auto-loaded |
src/EFCore/Properties/CoreStrings.resx |
Adds AutoLoadedConstructorProperty error message resource (also in .Designer.cs) |
src/EFCore.SqlServer/Metadata/Conventions/SqlServerAutoLoadConvention.cs |
Bug fix: adds UnwrapNullableType() to correctly detect nullable SqlVector<T>? types |
test/EFCore.Relational.Specification.Tests/Update/NonSharedModelUpdatesTestBase.cs |
Adds new test cases for the not-auto-loaded query scenarios; updates existing assertions to reflect new behavior (Description/Tags not materialized) |
test/EFCore.SqlServer.FunctionalTests/Update/NonSharedModelUpdatesSqlServerTest.cs |
SQL baselines for new and updated test methods |
test/EFCore.Tests/Infrastructure/ModelValidatorTest.cs |
Unit test for the new constructor-bound validation |
test/EFCore.SqlServer.FunctionalTests/Query/Translations/VectorTranslationsSqlServerTest.cs |
Updated SQL baselines: vector column excluded from SELECT |
test/EFCore.SqlServer.FunctionalTests/Scaffolding/CompiledModelSqlServerTest.cs |
Asserts IsAutoLoaded=false on the vector property in the compiled model test |
test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/Vector_index/VectorIndexEntityEntityType.cs |
Compiled model baseline: adds autoLoaded: false to vector property registration |
Files not reviewed (1)
- src/EFCore/Properties/CoreStrings.Designer.cs: Language not supported
You can also share your feedback on Copilot code review. Take the survey.
|
/azp run |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
|
||
| var typeName = structuralType.DisplayName(); | ||
|
|
||
| foreach (var consumedProperty in structuralType.ConstructorBinding.ParameterBindings |
There was a problem hiding this comment.
Move this to ValidateAutoLoaded since it's rare to have a non-autoloaded property
| structuralType.GetProperties().Cast<IPropertyBase>().Where(p => !p.IsShadowProperty() && p is not IProperty { IsAutoLoaded: false }) | ||
| .Concat(structuralType.GetComplexProperties().Where(p => !p.IsShadowProperty()))); |
There was a problem hiding this comment.
| structuralType.GetProperties().Cast<IPropertyBase>().Where(p => !p.IsShadowProperty() && p is not IProperty { IsAutoLoaded: false }) | |
| .Concat(structuralType.GetComplexProperties().Where(p => !p.IsShadowProperty()))); | |
| structuralType.GetProperties().Where(p => !p.IsShadowProperty() && !p.IsAutoLoaded).Cast<IPropertyBase>() | |
| .Concat(structuralType.GetComplexProperties().Where(p => !p.IsShadowProperty()))); |
Closes #37279