Fix ArgumentOutOfRangeException when deleting from ComplexCollection with nested collections#37702
Fix ArgumentOutOfRangeException when deleting from ComplexCollection with nested collections#37702Copilot wants to merge 8 commits intorelease/10.0from
Conversation
…with nested arrays Handle ArgumentOutOfRangeException when reading collection counts during state transitions in SetState. This fixes an issue where deleting an item from a ComplexCollection that contains arrays/lists would cause an exception during AcceptChanges when trying to read property values using out-of-range ordinals. Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
… counts Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Move ArgumentOutOfRangeException handling from SetState to GetOrCreateEntries to handle all cases where collection reading might fail due to out-of-range ordinals. Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
- Extract TryGetCollectionCount helper method to reduce code duplication - Add detailed documentation explaining when and why ArgumentOutOfRangeException occurs - Add initial state verification to test to ensure proper deletion behavior Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
src/EFCore/ChangeTracking/Internal/InternalEntryBase.InternalComplexCollectionEntry.cs
Outdated
Show resolved
Hide resolved
…ing state transitions Instead of catching exceptions defensively, fix the root cause by not reading from the CLR collection when it would require using out-of-bounds ordinals. During SetState after AcceptChanges, use the already-populated entries lists as the source of truth. In GetOrCreateEntries, catch the exception when reading from CLR fails and fall back to using the existing entries list. This addresses the feedback to fix the code that calculates indices rather than just catching exceptions. Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
|
@copilot Several tests are failing. Make sure to run all tests after fixing these: |
…nting CLR reads The previous approach of using _entries?.Count in SetState was incorrect because SetState is called during change detection (not just after AcceptChanges). During change detection, we need to read from the CLR collection to detect the new size. The fix now: 1. Always tries to read from CLR collection first 2. Falls back to existing entries list count only when ArgumentOutOfRangeException occurs 3. Applies this pattern in both SetState and GetOrCreateEntries Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
... Fixed in 704c6a1. The issue was that SetState is called during change detection (not just after AcceptChanges), so we need to read from the CLR collection to detect size changes. The fix now uses exception handling as a fallback only when ordinals are out of bounds, preserving normal change detection behavior. |
|
@copilot Update progress by rewriting the PR summary using this template: |
... Updated the PR description with the requested template format. |
src/EFCore/ChangeTracking/Internal/InternalEntryBase.InternalComplexCollectionEntry.cs
Outdated
Show resolved
Hide resolved
Instead of catching ArgumentOutOfRangeException, the fix now checks if the containing entry is a complex entry with an invalid ordinal (< 0) before attempting to read from the CLR collection. When the ordinal is invalid, it safely uses the existing entries list count as a fallback. Added AppContext switch "Microsoft.EntityFrameworkCore.Issue37585" to enable the old buggy behavior for customers who need it during migration. This avoids exceptions while properly handling the edge case of out-of-bounds ordinals during state transitions when deleting items from complex collections with nested collections. Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Description
When deleting an item from a ComplexCollection that contains nested arrays or lists, an
ArgumentOutOfRangeExceptionis thrown duringSaveChangesin theAcceptChangesphase. The database update succeeds, but the exception prevents normal completion of the operation.Customer impact
Customers cannot delete items from complex collections that contain nested collections/arrays using patterns like
entity.Collection = [.. entity.Collection.Where(predicate)]without encountering an exception. While the database is updated correctly, the exception disrupts the application flow and prevents proper error handling.Workaround: Use
RemoveAt()orClear()methods instead of reassigning the collection with filtered results, or enable the old behavior withAppContext.SetSwitch("Microsoft.EntityFrameworkCore.Issue37585", true).How found
Customer reported (issue #37585). At least one customer is affected based on the report and reactions (7 👍, 1 👀).
Regression
This appears to be a regression in EF Core 10.0.2.
Testing
Remove_element_from_complex_collection_using_Where_with_nested_arraytest that reproduces the exact scenarioRisk
Low. The changes are surgical and only affect reading collection counts when the containing entry has invalid ordinals:
Microsoft.EntityFrameworkCore.Issue37585) allows customers to use old behavior during migrationOriginal prompt
This section details on the original issue you should resolve
<issue_title>Deleting an item from a ComplexCollection, that contains an array results in Error</issue_title>
<issue_description>### Bug description
This may be resolved with the same fix as #37377; however, posting to be sure.
When deleting an item from a ComplexCollection, that Contains an array, an error is thrown.
Using the code below, calling SaveChanges(), results in an exception. What is unusual, is the save still goes through and the database result is correct.
Your code