Fix InvalidCastException in ArrayPropertyValues.ToObject() with nested nullable complex properties#37762
Open
AndriySvyryd wants to merge 1 commit intomainfrom
Open
Fix InvalidCastException in ArrayPropertyValues.ToObject() with nested nullable complex properties#37762AndriySvyryd wants to merge 1 commit intomainfrom
AndriySvyryd wants to merge 1 commit intomainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Fixes change-tracking value materialization for nested nullable complex properties (and related SetValues/OriginalValues behavior), addressing InvalidCastException scenarios like #37516 and ensuring compiled model scaffolding emits the necessary factories.
Changes:
- Add/propagate nullable complex-property null-state handling across
PropertyValuesimplementations andSetValues(...)flows. - Introduce
EmptyOriginalValuesFactoryplumbing to avoid initializing original snapshots from uninitialized complex collections (including compiled model scaffolding/baselines). - Add/expand unit tests covering
ToObject()/SetValues(...)with nested nullable complex properties and complex collections.
Reviewed changes
Copilot reviewed 116 out of 116 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/EFCore/ChangeTracking/PropertyValues.cs | Centralize computation of nullable complex properties for null-state tracking. |
| src/EFCore/ChangeTracking/Internal/EntryPropertyValues.cs | Propagate nullable-complex null-state + enhance SetValues for nested complex scenarios. |
| src/EFCore/ChangeTracking/Internal/ArrayPropertyValues.cs | Adjust ToObject/SetValues for nested nullable complex properties and complex collections. |
| src/EFCore/ChangeTracking/Internal/OriginalPropertyValues.cs | Reconstruct original complex-collection elements from per-entry original snapshots. |
| src/EFCore/ChangeTracking/Internal/InternalEntryBase.cs | Add skip-change-detection option for setting originals; avoid snapshot init when ordinals out of bounds. |
| src/EFCore/ChangeTracking/Internal/InternalEntryBase.OriginalValues.cs | Add empty-original-values snapshot path. |
| src/EFCore/ChangeTracking/Internal/InternalEntryBase.InternalComplexCollectionEntry.cs | Ensure original values exist when transitioning complex-collection state. |
| src/EFCore/ChangeTracking/Internal/InternalComplexEntry.cs | Guard original-value reads on snapshot availability for deleted entries. |
| src/EFCore/ChangeTracking/Internal/IInternalEntry.cs | Extend SetOriginalValue API with skip-change-detection option. |
| src/EFCore/ChangeTracking/Internal/CurrentPropertyValues.cs | Thread skip-change-detection through SetValueInternal override. |
| src/EFCore/ChangeTracking/Internal/EmptyOriginalValuesFactoryFactory.cs | New factory to generate empty original-values snapshots. |
| src/EFCore/Metadata/Internal/IRuntimeTypeBase.cs | Add EmptyOriginalValuesFactory to runtime metadata surface. |
| src/EFCore/Metadata/Internal/TypeBase.cs | Provide lazy-initialized EmptyOriginalValuesFactory implementation. |
| src/EFCore/Metadata/RuntimeTypeBase.cs | Add runtime setter/getter for EmptyOriginalValuesFactory (compiled model support). |
| src/EFCore.Design/Scaffolding/Internal/CSharpRuntimeModelCodeGenerator.cs | Emit SetEmptyOriginalValuesFactory into generated runtime model code. |
| test/EFCore.Tests/ChangeTracking/Internal/PropertyValuesTest.cs | Add coverage for ToObject/SetValues with nested nullable complex properties/collections. |
| test/EFCore.Specification.Tests/TestUtilities/DataGenerator.cs | Support nullable enum inputs for combinatorial test data. |
| test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/Triggers/DataEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/SimpleModel/DependentDerivedEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/Dynamic_schema/DataEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/DbFunctions/ObjectEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/DbFunctions/DataEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/CheckConstraints/DataEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel_with_JSON_columns/PrincipalDerivedEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel_with_JSON_columns/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel_with_JSON_columns/PrincipalBaseEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel_with_JSON_columns/OwnedTypeEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel_with_JSON_columns/OwnedType0EntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel_with_JSON_columns/DependentDerivedEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel_with_JSON_columns/DependentBaseEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel_with_JSON_columns/DataEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel_with_JSON_columns/AutoIncrementEntityEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalDerivedEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBaseEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel/OwnedTypeEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel/OwnedType0EntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel/DependentDerivedEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel/DependentBaseEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel/DataEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Sqlite.FunctionalTests/Scaffolding/Baselines/BigModel/AutoIncrementEntityEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/Triggers/DataEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/Tpc_Sprocs/PrincipalDerivedEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/Tpc_Sprocs/PrincipalBaseEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/Tpc_Sprocs/DependentBaseEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/SpatialTypesTest/SpatialTypesEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/SimpleModel/DependentDerivedEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/Key_sequence/DataEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/Key_HiLo_sequence/DataEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/Dynamic_schema/DataEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/DbFunctions/ObjectEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/DbFunctions/DataEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalDerivedEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalBaseEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/CheckConstraints/DataEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/BigModel_with_JSON_columns/PrincipalDerivedEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/BigModel_with_JSON_columns/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/BigModel_with_JSON_columns/PrincipalBaseEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/BigModel_with_JSON_columns/OwnedTypeEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/BigModel_with_JSON_columns/OwnedType0EntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/BigModel_with_JSON_columns/DependentDerivedEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/BigModel_with_JSON_columns/DependentBaseEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalDerivedEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBaseEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/BigModel/OwnedTypeEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/BigModel/OwnedType0EntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/BigModel/DependentDerivedEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/BigModel/DependentBaseEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/SimpleModel/DependentDerivedEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Self_referential_property/SelfReferentialEntityEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/RelationshipCycles/PrincipalDerivedEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/RelationshipCycles/PrincipalBaseEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/RelationshipCycles/DependentBaseEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Manual_lazy_loading/LazyPropertyEntityEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Manual_lazy_loading/LazyPropertyDelegateEntityEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Manual_lazy_loading/LazyConstructorEntityEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Lazy_loading_proxies/LazyProxiesEntity2EntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Lazy_loading_proxies/LazyProxiesEntity1EntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Lazy_loading_manual/LazyProxiesEntity4EntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Lazy_loading_manual/LazyProxiesEntity3EntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Global_namespace/EntityType1.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Fully_qualified_model/ScaffoldingEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Fully_qualified_model/IndexEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Fully_qualified_model/IdentityUserEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Fully_qualified_model/IdentityUser0EntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Custom_value_converter/MyEntityEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Custom_value_comparer/MyEntityEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Custom_type_mapping/MyEntityEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/Custom_provider_value_comparer/MyEntityEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalDerivedEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalBaseEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalDerivedEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBaseEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/BigModel/OwnedTypeEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/BigModel/OwnedType0EntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/BigModel/DependentDerivedEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.InMemory.FunctionalTests/Scaffolding/Baselines/BigModel/DependentBaseEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/SimpleModel/DependentDerivedEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalDerivedEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalBaseEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalDerivedEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBaseEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/OwnedTypeEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/OwnedType0EntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/ManyTypesEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/DependentDerivedEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/DependentBaseEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
| test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/Basic_cosmos_model/DataEntityType.cs | Baseline updated for emitted EmptyOriginalValuesFactory. |
src/EFCore/ChangeTracking/Internal/EmptyOriginalValuesFactoryFactory.cs
Outdated
Show resolved
Hide resolved
ee1efec to
09f589a
Compare
…d nullable complex properties Fix issues with SetValues methods with nested nullable complex properties Fixes #37516 Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
09f589a to
f9b0d1a
Compare
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.
Fix issues with SetValues methods with nested nullable complex properties
Handle uninitialized complex collections when creating the initial original values.
Fixes #37516