Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
567 changes: 292 additions & 275 deletions src/EFCore.Relational/Update/ModificationCommand.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public ComplexElementEntry(InternalComplexEntry internalEntry)
/// </param>
/// <returns>An object that exposes change tracking information and operations for the given property.</returns>
public virtual PropertyEntry<TEntity, TProperty> Property<TProperty>(
Expression<Func<TComplexProperty, TProperty>> propertyExpression)
Expression<Func<TComplexProperty, TProperty?>> propertyExpression)
{
Check.NotNull(propertyExpression, nameof(propertyExpression));

Expand Down
2 changes: 1 addition & 1 deletion src/EFCore/ChangeTracking/ComplexPropertyEntry`.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ public virtual PropertyEntry<TEntity, TProperty> Property<TProperty>(
/// </param>
/// <returns>An object that exposes change tracking information and operations for the given property.</returns>
public virtual ComplexPropertyEntry<TEntity, TNestedComplexProperty> ComplexProperty<TNestedComplexProperty>(
Expression<Func<TComplexProperty, TNestedComplexProperty>> propertyExpression)
Expression<Func<TComplexProperty, TNestedComplexProperty?>> propertyExpression)
{
Check.NotNull(propertyExpression);

Expand Down
2 changes: 1 addition & 1 deletion src/EFCore/ChangeTracking/EntityEntry`.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public virtual PropertyEntry<TEntity, TProperty> Property<TProperty>(
/// </param>
/// <returns>An object that exposes change tracking information and operations for the given property.</returns>
public virtual ComplexPropertyEntry<TEntity, TProperty> ComplexProperty<TProperty>(
Expression<Func<TEntity, TProperty>> propertyExpression)
Expression<Func<TEntity, TProperty?>> propertyExpression)
{
Check.NotNull(propertyExpression);

Expand Down
2 changes: 1 addition & 1 deletion src/EFCore/ChangeTracking/Internal/ChangeDetector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -321,11 +321,11 @@ public bool DetectComplexCollectionChanges(InternalEntryBase entry, IComplexProp

Check.DebugAssert(!complexProperty.ComplexType.ClrType.IsValueType, $"Expected {complexProperty.Name} to be a collection of reference types.");

var changesFound = false;
var originalEntries = new Dictionary<object, InternalComplexEntry>(ReferenceEqualityComparer.Instance);
var currentCollection = (IList?)entry[complexProperty];
// The elements in the original collection might be the same instances as in the current collection, so their properties shouldn't be used for comparison.
var originalCollection = (IList?)entry.GetOriginalValue(complexProperty);
var changesFound = (currentCollection == null) != (originalCollection == null);

entry.EnsureComplexCollectionEntriesCapacity(complexProperty, currentCollection?.Count ?? 0, originalCollection?.Count ?? 0, trim: false);
var originalNulls = new HashSet<int>();
Expand Down
5 changes: 3 additions & 2 deletions src/EFCore/ChangeTracking/Internal/InternalComplexEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,9 @@ protected override void OnStateChanged(EntityState oldState)
/// </summary>
public override void AcceptChanges()
{
if (EntityState == EntityState.Added
|| ContainingEntry.GetComplexCollectionEntry(ComplexProperty, Ordinal) == this)
if (Ordinal != -1
&& (EntityState == EntityState.Added
|| ContainingEntry.GetComplexCollectionOriginalEntry(ComplexProperty, Ordinal) == this))
{
OriginalOrdinal = Ordinal;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -149,24 +149,31 @@ public void AcceptChanges()

if (_originalEntries != null)
{
foreach (var entry in _originalEntries)
for (var i = 0; i < _originalEntries.Count; i++)
{
var entry = _originalEntries[i];
if (entry == null
|| entry.EntityState != EntityState.Deleted)
{
continue;
}
entry.AcceptChanges();
// The entry was deleted, so AcceptChanges removed it from the list
i--;
}
}

if (_entries != null)
{
_originalEntries = new List<InternalComplexEntry?>(_entries.Count);
foreach (var entry in _entries)
_originalEntries ??= new List<InternalComplexEntry?>(_entries.Count);
_originalEntries.Clear();
for (var i = 0; i < _entries.Count; i++)
{
_originalEntries.Add(_entries[i]);
}
for (var i = 0; i < _originalEntries.Count; i++)
{
_originalEntries.Add(entry);
entry?.AcceptChanges();
_originalEntries[i]?.AcceptChanges();
}
}
else
Expand Down Expand Up @@ -195,10 +202,14 @@ public void RejectChanges()

if (_originalEntries != null)
{
_entries = new List<InternalComplexEntry?>(_originalEntries.Count);
foreach (var entry in _originalEntries)
_entries ??= new List<InternalComplexEntry?>(_originalEntries.Count);
_entries.Clear();
for (var i = 0; i < _originalEntries.Count; i++)
{
_entries.Add(_originalEntries[i]);
}
foreach (var entry in _entries)
{
_entries.Add(entry);
entry?.Ordinal = entry.OriginalOrdinal;
}
}
Expand Down
Loading