You can define what users are told, and what must be true, before an object is deleted by setting business delete rules on association ends and by creating delete constraints in your model.
Deletion has two separate concerns:
- Technical deletion behavior determines what happens to related objects and links when an object is deleted. This is governed by aggregation and delete behavior.
- Business deletion behavior expresses whether deleting an object is acceptable while related objects remain. Business delete rules help your application communicate and enforce that decision consistently.
Use the delete operator to mark an object for removal. The object is permanently removed at the next save operation. Business delete rules and delete constraints are evaluated as part of deletion performed by MDriven.
Set a business delete rule on an association end
Each association end has a BusinessDeleteRule value. Set the value that describes the business meaning of deleting an object while that association end contains related objects.
For example, consider a Brand class with an AllCarsOfThisBrand association to Car. If a brand must remain while cars still refer to it, set the rule on AllCarsOfThisBrand to MustBeEmpty. In the opposite direction, deleting a car can be acceptable even though the car has a brand; set that association end to NeedNotBeEmptyNoWarning.
| BusinessDeleteRule value | Meaning when the association end is not empty | Typical use |
|---|---|---|
| NotDecided | No business decision has been modeled for this association end. This is the default value. | Use temporarily while you decide the rule. Do not treat it as a replacement for a modeled business decision. |
| MustBeEmpty | Deletion is not acceptable while related objects remain on this end. | A Brand must not be deleted while cars remain in AllCarsOfThisBrand. |
| NeedNotBeEmptyButWarn | Deletion is acceptable, but the user must be informed that related objects remain. | Deleting a customer is permitted, but the user should be told that related contact records still exist. |
| NeedNotBeEmptyNoWarning | Deletion is acceptable and does not require a warning for this association end. | Deleting a Car is acceptable even though it is associated with a Brand. |
Choose the rule deliberately
For every association end, ask the question from the perspective of the object being deleted: May this object be deleted when this end contains related objects?
- Choose MustBeEmpty when the answer is no.
- Choose NeedNotBeEmptyButWarn when the answer is yes, but the remaining relationships are relevant to the userâs decision.
- Choose NeedNotBeEmptyNoWarning when the relationship should not affect the deletion decision.
- Replace NotDecided once the domain rule is known.
BusinessDeleteRule describes a business decision; it does not replace the technical rules of aggregation or cascading delete. A deletion can still fail because the object being deleted, or an object included through cascading deletion, is not technically ready for deletion. For handling such technical delete reasons dynamically, see OnDelete and OnDeleteReasonSolve.
How the delete service informs the user
The standard delete handling uses IBusinessDeleteService. For association ends configured as NeedNotBeEmptyButWarn, NotDecided, or MustBeEmpty, the service can inform the user about the relevant condition.
The standard implementation exposes the IBusinessDeleteService.OnInformTheUser event. You can handle this event to present the message in the user interface, or provide your own implementation of IBusinessDeleteService when your application needs different interaction behavior.
The UI is responsible for presenting information to the user; the model remains the place where the business decision is defined. This keeps the same deletion rules available regardless of which ViewModel or client invokes the delete.
Add explicit delete constraints
Use a delete constraint when the rule depends on attributes, state, or a combination of relationships that cannot be expressed by checking whether one association end is empty.
A constraint is a model-level OCL rule that evaluates to true or false. Mark a constraint with IsDeleteConstraint when it should be evaluated specifically during deletion.
For example, a Car must not be deleted while it has a deposit, unless its state is Scrapped. Model that rule as a delete constraint on Car. The rule expresses the business policy in the model rather than in a button handler or UI-specific delete flow.
When a delete constraint is broken, the default IBusinessDeleteService calls OnInformTheUser with the constraint message. In WECPOF, the message is shown to the user and deletion is stopped until the constraint break is corrected.
Define a delete constraint
- Create a constraint on the class that owns the deletion rule.
- Enter an OCL expression that evaluates to true only when deletion is permitted.
- Write a message that tells the user what must change before deletion can continue. You can use
<asString>in the description to include the broken objectâs string representation. - Set IsDeleteConstraint for the constraint.
- Delete an instance through the normal MDriven deletion path and verify both the permitted and blocked cases.
For general constraint design, severity, and use in ViewModels, see Training:Constraints. For input and data validation that applies while users edit values rather than only during deletion, see data validation.
Use association rules and delete constraints together
Association-end rules and delete constraints solve different parts of the deletion policy.
| Requirement | Model it with | Example |
|---|---|---|
| The object must have no related objects on one association end. | BusinessDeleteRule = MustBeEmpty | A Brand cannot be deleted while it has Cars. |
| The object may be deleted, but the user should be made aware of related objects. | BusinessDeleteRule = NeedNotBeEmptyButWarn | A customer may be deleted after the user is informed that contact records remain. |
| Deletion depends on state or other business data. | A constraint with IsDeleteConstraint | A Car with a deposit may be deleted only in the Scrapped state. |
| The deletion graph needs technical correction before deletion can proceed. | OnDeleteReasonSolve | Clear or otherwise resolve a relationship that blocks a cascade delete when the modeled policy permits it. |
Test the deletion policy
Test each delete path from the perspective of the user and the model:
- Create an object with related objects on each association end covered by a business delete rule.
- Attempt deletion when an end configured as MustBeEmpty is populated; verify that deletion is not allowed.
- Attempt deletion when an end configured as NeedNotBeEmptyButWarn is populated; verify that the user receives the intended information.
- Attempt deletion when a delete constraint evaluates to false; verify that its message identifies the condition that must be fixed.
- Correct the blocking condition and repeat the deletion.
- Save and verify the expected persistence result.
Do not duplicate these rules in UI code. Invoke deletion through the model-aware delete flow so that association-end rules and delete constraints are evaluated consistently. An MVC example of calling BusinessDelete before committing is described in MVC View Model constraints.
