🚀 Welcome to MDriven Learn –  MDriven is now on Discord!  Don’t miss the latest Release Notes.
OCLOperators OnDelete
This page was created by Hans.karlsen on 2022-04-05. Last edited by Wikiadmin on 2026-07-29.

You can use OnDelete to run EAL when an object is deleted, and use OnDeleteReasonSolve to remove a specific relationship that is blocking a cascading delete.

Use OnDelete for delete-time work

OnDelete is a special, framework-recognized method name. It is called when an object is deleted, similar to a destructor. Use it for work that must happen as part of deleting an object, such as recording that the object was deleted.

OnDelete can also run for objects that are deleted as a consequence of a cascading delete. A delete can fail when the object being deleted, or an object reached through the cascade, still has associations that are not included in that cascade.

OnDelete is an object event method. Set its IsQuery property to false, because it performs changes and is therefore EAL rather than side-effect-free OCL.

Example: archive the identifier of a deleted object

The following OnDelete body creates an archive object and copies the deleted object's Guid to it:

let deleted = DeletedObj.Create in
(
  deleted.DeletedGuid := self.Guid
)

Use an archive class such as DeletedObj when you need a durable record of which object was deleted. The class and property names in this example must exist in your model.

Understand why a cascading delete can stop

A cascading delete follows the model's composite association ends. An association that is aggregate but not part of the cascade can prevent deletion when it is still non-empty.

For example, assume that deleting a Class1 object cascades through most of its composite associations. During that cascade, a Class4 object is reached. If its association to Class3 objects is aggregate only, rather than included in the cascade, the delete can stop because the Class4-Class3s association end is not empty.

Do not treat every failed delete as something to override. First determine whether the remaining association should be cleared as part of the business rule. If it should remain, the delete should continue to fail.

Resolve a known delete blocker with OnDeleteReasonSolve

Implement OnDeleteReasonSolve when a delete may be blocked by a relationship that your model is allowed to change dynamically. This is also a special, framework-recognized method name.

Use this method signature:

OnDeleteReasonSolve(reason:string; objectschecked:Collection(SysSuperClass))
Parameter Meaning
reason The reason reported for the current delete failure.
objectschecked The objects already checked in the delete graph. This projects the delete topology and lets you apply a rule only when a particular path or object is involved.

The objectschecked parameter was added on 2025-03-18. Type this collection to the most general superclass available in your model; use object when that is the appropriate common type.

Example: clear a blocking Class3 association

In the Class1/Class4/Class3 scenario, the following EAL checks whether the relevant Class1 object is present in the checked delete graph. If it is, the action clears self.Class3s, allowing the delete check to run again:

(objectschecked.indexof0(self.Class1)>-1)->whentrue(self.Class3s->clear)

Adapt Class1 and Class3s to the actual roles in your model. This example clears the association; it does not state that the Class3 objects themselves are deleted.

What happens after OnDeleteReasonSolve

  1. MDriven performs the delete check.
  2. If it finds no reason to block deletion, it does not call OnDeleteReasonSolve.
  3. If it finds a reason, it calls OnDeleteReasonSolve with that reason and the checked objects.
  4. MDriven checks deletion again after the method has acted.
  5. If another unresolved reason remains, OnDeleteReasonSolve is called again with the new top reason.
  6. If your method does not resolve all blocking reasons, deletion fails and the user receives the exception that states the reason.

This retry behavior means that your method must resolve the complete current blocker. A rule that clears one association can expose another non-empty association on the next check.

Design guidance

  • Use OnDelete for work that belongs to the deletion of an individual object, such as deletion logging.
  • Use OnDeleteReasonSolve only for deliberate rules that remove a known blocker in the delete graph.
  • Use objectschecked when the same object type can be reached from different delete paths and the action must apply only to one of them.
  • Keep the method non-query (EAL), because clearing an association changes model objects.

See also