🚀 Welcome to MDriven Learn –  MDriven is now on Discord!  Don’t miss the latest Release Notes.
Acting on object changes
This page was created by Lars.olofsson on 2017-07-25. Last edited by Wikiadmin on 2026-07-29.

You can use EAL event methods on model classes to initialize, update, and archive model objects when they are created, saved, or deleted; this page is for MDriven Designer modelers who need automatic object-lifecycle behavior.

Use EAL to change model objects

OCL expressions are side-effect free: they calculate and navigate but do not assign values or otherwise change the model. A ViewModel expression is therefore OCL; it defines a projection of model data for a ViewModel and must not alter that data.

Use an EAL method when your expression must change an object. EAL uses assignments and operations such as Create to act on model objects. Typical places to use EAL are:

  • Lifecycle event methods on a class, such as OnCreate and OnUpdate.
  • Actions that a user executes.
  • Other non-query methods that intentionally change model objects.

A class method marked IsQuery is an OCL query method. It is side-effect free and can be called from other OCL expressions. A method that changes objects must have IsQuery set to false.

Handle object lifecycle events

MDriven recognizes the following hard-coded method names when they are present on a class. Set IsQuery to false for all three methods.

Method name When it runs Use it for Important limit
OnCreate After a new object has been created. Initial values, such as a creation timestamp or GUID. Call self.base.OnCreate when the superclass implementation must also run.
OnUpdate Immediately before the object is saved to the database. Values that must be refreshed on every save, such as a change timestamp. Do not create objects here. A newly created object from an OnUpdate action will be left unsaved.
OnDelete When the object is deleted. Recording deletion information in an archive class. Keep only the information that must remain after the original object is gone.

For the save lifecycle and save behavior, see Save. For details specific to each event, see OnCreate and OnUpdate.

Add lifecycle methods to a class

  1. In MDriven Designer, select the class that owns the attributes and behavior.
  2. Add a method named exactly OnCreate, OnUpdate, or OnDelete, depending on the event you need.
  3. Set the method's IsQuery setting to false.
  4. Enter the EAL expression in the method body.
  5. Save and test the relevant lifecycle operation: create an object, save a changed object, or delete an object.

The method names are significant. MDriven triggers OnCreate, OnUpdate, and OnDelete by these names when it finds them on the class.

Example: apply timestamps and a GUID

A common model hygiene pattern is to give each persistent business object:

  • CreateTime for when it was created.
  • ChangeTime for when it was last saved.
  • Guid for a globally unique identifier that can be retained when data is exchanged with other systems.

For example, a class such as Order can use the following methods.

Initialize a new object

Add a non-query OnCreate method:

CreateTime:=DateTime.Now;
self.Guid.newGuid()

This assigns the creation time and generates a new GUID for the new Order.

If the class inherits lifecycle behavior from a superclass, call the superclass implementation as needed:

self.base.OnCreate

Stamp each saved update

Add a non-query OnUpdate method:

if self.existing then -- This avoids touching the object if it has been deleted
  self.ChangeTime:=DateTime.Now;
  false
else
  false
endif

self.existing prevents the method from changing an object that has already been deleted. The final false is part of this event expression pattern.

Do not add DeletedObj.Create, or any other object creation, to OnUpdate. Objects created during OnUpdate are not saved.

Archive a deleted object's GUID

If your model has an archive class named DeletedObj with an attribute DeletedGuid, add a non-query OnDelete method:

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

For example, deleting an Order with GUID ... creates a DeletedObj record that retains that GUID. An integration can then discover that the previously exported object no longer exists.

Put shared behavior in a default superclass

When many classes need the same timestamps, GUID, and deletion logging, place the attributes and lifecycle methods on a shared superclass. Set that superclass as the package's default superclass so new classes in the package inherit the behavior.

This avoids copying the same three methods to every business class. A new class, such as Customer, then receives CreateTime, ChangeTime, Guid, and the lifecycle behavior through inheritance. See Object Identity for the complete default-superclass pattern and its integration rationale.

Choose event methods or actions deliberately

Use lifecycle methods for rules that must run because an object changes, regardless of which user interface or process initiated the change. For example, ChangeTime belongs in OnUpdate because every save should update it.

Use an action for an operation a user chooses to perform. When the operation acts on one selected instance, a class action is usually appropriate: it becomes available where that class instance is shown. See Class actions for this usage pattern.

Do not put model-changing assignments in a ViewModel expression. For example, a ViewModel expression may calculate which orders to show, while an action or non-query class method changes an order's status.

Do not confuse lifecycle events with database change tracking

Lifecycle methods react to changes made through the MDriven model. They are not a way to discover direct updates made by another system against SQL Server tables. If an external system writes to the same database, use the separate SQL Server change tracking pattern to invalidate affected objects in MDrivenServer.

See also