---
title: Save managed business collection
summary: Validates and persists a managed business collection by saving deleted children first and then active children.
status: draft
owner: SAIF
last_reviewed: 2026-07-30
library: SAIF.Framework.Core
reference_type: package
operation_id: OP-CORE-006
trigger: Caller invokes Save() or parent logic invokes SaveChild() on a managed business collection.
---

# Save managed business collection

This operation is the collection-level persistence workflow for managed `clsBusinessCollectionBase` instances. It validates the collection and its children, persists every deferred deletion before touching any active item, and then persists active children in order — stopping the entire save immediately, and propagating the failing child's broken rules to the collection, the moment any child save returns `False`.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-CORE-006 |
| **Trigger** | Caller invokes `Save()` on a managed root collection or parent logic invokes `SaveChild()` on a child collection. |
| **Inputs** | Collection state flags, deleted-child list, active child list, and each child's `CriteriaObject`. |
| **Outputs** | Persisted deleted children, persisted active children, or early failure with propagated rules. |
| **Primary components** | `clsBusinessCollectionBase.Save`, `clsBusinessCollectionBase.SaveChild` |
| **Entry point** | `SAIF.Framework.Core\V1\BaseItems\clsBusinessCollectionBase.vb` |

## Steps

1. Validate collection entry conditions before any child save runs.
   - The collection must be `Managed = True`.
   - Root save rejects child collections; child save rejects non-child collections.
   - Both entry points reject open edit levels and invalid collections before work begins ([BR-001](../business-rules.md#br-001-rule-registration-and-enforcement-framework), [BR-002](../business-rules.md#br-002-broken-rule-tracking-and-surfacing)).
2. Re-evaluate collection validity ([BR-001](../business-rules.md#br-001-rule-registration-and-enforcement-framework), [BR-002](../business-rules.md#br-002-broken-rule-tracking-and-surfacing)).
   - `IsValid` validates child items first, optionally short-circuiting when `ValidateAllChildren = False`.
   - It then checks the collection's own rules and propagates child messages upward ([BR-002](../business-rules.md#br-002-broken-rule-tracking-and-surfacing)).
3. Clear current errors and warnings and short-circuit unchanged collections.
   - `Rules.BrokenRules.ClearErrorsAndWarnings()` resets the collection's transient error/warning state ([BR-002](../business-rules.md#br-002-broken-rule-tracking-and-surfacing)).
   - If `IsDirty = False`, the operation returns `True` without touching children.
4. Start the save phase by calling `OnSave()`.
5. Persist deferred deletions before active items.
   - For each item in `m_deletedList`, call `BusinessObject.SaveChild()`.
   - If any child returns `False`, propagate that child's rules to the collection and stop immediately ([BR-002](../business-rules.md#br-002-broken-rule-tracking-and-surfacing)).
6. Clear the deleted list only after all deferred deletes succeed.
7. Persist active child items in collection order.
   - For each current child, call `BusinessObject.SaveChild()`.
   - If any child returns `False`, propagate that child's rules to the collection and stop immediately ([BR-002](../business-rules.md#br-002-broken-rule-tracking-and-surfacing)).

   > **Origin**: The per-child persistence executed in steps 5 and 7 follows the single-object workflow documented in [Save business object](save-business-object.md), implemented by `clsBusinessBase.SaveChild()` in this same library.
8. Complete the save only when every child succeeds.
   - `OnSaveComplete()` runs after all deleted and active children finish successfully.
   - The operation returns `True`.

## Process flow

The following diagram visualizes this operation's control flow.

```mermaid
flowchart TD
	Start([Collection Save]) --> Valid{Managed and valid?}
	Valid -->|No| EndErr([Throw ApplicationException])
	Valid -->|Yes| Dirty{Dirty?}
	Dirty -->|No| EndNoop([Return true])
	Dirty -->|Yes| Deleted[Save deleted children]
	Deleted --> DeletedOk{All deleted children saved?}
	DeletedOk -->|No| EndFail([Propagate child rules and stop])
	DeletedOk -->|Yes| Active[Save active children]
	Active --> ActiveOk{All active children saved?}
	ActiveOk -->|No| EndFail
	ActiveOk -->|Yes| Done[Run OnSaveComplete]
	Done --> EndOk([Return true])
```

## Failure and edge-case behavior

- An unmanaged collection (`Managed = False`) is rejected before any child processing starts, and a root/child role mismatch is rejected the same way.
- The deferred-deletion phase must fully succeed for every item in `m_deletedList` before that list is cleared; a partial failure leaves the deleted list intact so a retry does not lose track of pending deletions.
- The save stops at the first child that returns `False` — later children in that same phase are never attempted during that save call, even if they would have succeeded.

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)

## Sources
- SAIF.Framework.Core\V1\BaseItems\clsBusinessCollectionBase.vb
- SAIF.Framework.Core\V1\BaseItems\clsBusinessBase.vb
