Skip to content

Commit abfe213

Browse files
committed
Ensure that ClearItems() enforces business logic
Previously, when deleting items directly via `Clear()`, the `ClearItems()` wouldn't enforce business logic. This is problematic because sometimes properties either a) disallow nulls, or b) must update their internal states when values are set to null. This would be handled when calling `SetValue()` or going directly through the property, but bypassed when calling `Clear()`. Unfortunately, for `Clear()`, this means checking the business logic for each individual record. As such, instead of just bulk deleting these, we're instead calling `Remove()` for each individual item. This is less performant, but ensures that the business logic is always accounted for. Fortunately, calling `Clear()` on this collection is uncommon; it's far more common to work with individual items via `SetValue()` or, less commonly, `Remove()`. This update patches that hole, and thus resolves the `Clear()` portion of #79.
1 parent 0bccf1f commit abfe213

File tree

1 file changed

+7
-4
lines changed

1 file changed

+7
-4
lines changed

OnTopic/Collections/Specialized/TrackedRecordCollection{TItem,TValue,TAttribute}.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -625,12 +625,15 @@ protected override void RemoveItem(int index) {
625625
/// it is appropriately marked as <see cref="IsDirty()"/>.
626626
/// </summary>
627627
/// <remarks>
628-
/// When an <see cref="TrackedRecord{T}"/> is removed, <see cref="IsDirty()"/> will return true—even if no remaining <see
629-
/// cref="TrackedRecord{T}"/>s are marked as <see cref="TrackedRecord{T}.IsDirty"/>.
628+
/// In order to ensure any business logic is enforced, <see cref="ClearItems()"/> loops through every <see cref="
629+
/// TrackedRecord{T}"/> in the <see cref="TrackedRecordCollection{TItem, TValue, TAttribute}"/> and explicitly calls <see
630+
/// cref="KeyedCollection{TKey, TItem}.Remove(TKey)"/>. This is slower, but ensures that any state tracking and null
631+
/// validation that occurs in the properties is maintained. Fortunately, this is a rare use case; we typically expect
632+
/// attributes to be handled individually.
630633
/// </remarks>
631634
protected override void ClearItems() {
632-
if (!AssociatedTopic.IsNew) {
633-
DeletedItems.AddRange(Items.Select(a => a.Key));
635+
foreach (var item in Items) {
636+
Remove(item);
634637
}
635638
base.ClearItems();
636639
}

0 commit comments

Comments
 (0)