Search Results for

    Show / Hide Table of Contents

    Events

    Aurelius provides an event system which you can use to receive callback notifications when some events occur, for example, an entity update or a item is included in a collection. This chapter explains how to use this event system and what events are available.

    Using Events

    Subscribing from code

    Events in Aurelius are available in the Events property of the TMappingExplorer object. Such property refers to a TManagerEvents (declared in unit Aurelius.Events.Manager) object with several subproperties, each to them related to an event. For example, to access the OnInserted event of the default TMappingExplorer:

    uses {...}, Aurelius.Mapping.Explorer, Aurelius.Events.Manager;
    
    TMappingExplorer.Default.Events.OnInserted.Subscribe(
      procedure(Args: TInsertedArgs)
      begin
        // Use Args.Entity to retrieve the inserted entity
      end
    );
    
    TMappingExplorer.Default.Events.OnUpdated.Subscribe(
      procedure(Args: TUpdatedArgs)
      begin
        // Use Args.Entity to retrieve the updated entity
      end
    );
    

    In a less direct way, using method reference instead of anonymous method:

    uses {...}, Aurelius.Mapping.Explorer, Aurelius.Events.Manager;
    
    procedure TSomeClass.MyInsertedProc(Args: TInsertedArgs);
    begin
      // Use Args.Entity to retrieve the inserted entity
    end;
    
    procedure TSomeClass.MyUpdatedProc(Args: TUpdatedArgs);
    begin
      // Use Args.Entity to retrieve the updated entity
    end;
    
    procedure TSomeClass.RegisterMyEventListeners;
    var
      Events: TManagerEvents;
    begin
      Events := TMappingExplorer.Default.Events;
      Events.OnInserted.Subscribe(MyInsertedProc);
      Events.OnUpdated.Subscribe(MyUpdatedProc);
    end;
    

    The events are available in the TMappingExplorer object so the listeners will receive notifications about any event fired by any TObjectManager created that references the specified TMappingExplorer object. In other words, the events are "global" for that mapping explorer.

    Listeners are method references that receive a single object as a parameter. Such object has several properties containing relevant information about the event, and differ for each event type. Names of event properties, method reference type and arguments follow a standard. The event property is named "On<event>", method reference type is "T<event>Proc" and parameter object is "T<event>Args". For example, for the "Deleted" event, the respective names will be "OnDeleted", "TDeletedProc" and "TDeletedArgs".

    All events in Aurelius are multicast events, which means you can add several events handlers (listeners) to the same event. When an event occurs, all listeners will be notified. This allows you to add a listener in a safe way, without worrying if it will replace an existing listener that might have been set by other part of the application. You should use Subscribe and Unsubscribe methods to add and remove listeners, respectively. Note that since listeners are method references, you must sure to unsubscribe the same reference you subscribed to:

    var
      LocalProc: TInsertedProc;
    begin
      LocalProc := MyInsertedProc;
      Events.OnInserted.Subscribe(LocalProc);
      {...}
      Events.OnInserted.Unsubscribe(LocalProc);
    end;
    

    Passing just the method name doesn't work:

    Events.OnInserted.Subscribe(MyInsertedProc);
    {...}
    // this will NOT unsubscribe the previous subscription:
    Events.OnInserted.Unsubcribe(MyInsertedProc);
    

    TAureliusModelEvents Component

    An alternative, more RAD way to use events is the TAureliusModelEvents component. Just drop the component in the form and double click the desired event in the object inspector to create an event handler.

    The events available are exactly the same ones that you can set from code, like OnInserting, OnSqlExecuting, etc. See all the available events in this chapter.

    Key properties

    Name Description
    ModelName: string The name(s) of the model(s) to be used by the manager. You can leave it blank, if you do it will use the default model. Two or more model names should be separated by comma. From the model names it will get the property TMappingExplorer component that will be passed to the TDatabaseManager constructor to create the instance that will be encapsulated.

    Note the events are "cumulative", the same way you do it from code. It means that if you add two or more TAureliusModelEvents in your application and set an event handler for the same event in all of them, all the handlers will be fired. That's very convenient to event handler code that is specific to each context in your app.

    Using Attributes

    A third and even more straightforward way to respond to events is to use attributes. You can simply add an attribute to a method of an entity class, and that method will be invoked when the event is triggered. Consider the following example:

    type
      {$RTTI EXPLICIT METHODS([vcPrivate..vcPublished])}
      TCustomer = class
      strict private
        [OnInserting] procedure OnInserting(Args: TInsertingArgs);
        [OnInserted] procedure OnInserted;
    
        [OnUpdated, OnInserted] procedure AfterModification;
      {...}
      end;
    

    When TCustomer entity is about to be inserted in the database, the OnInserting method will be invoked. After the record is inserted, the method OnInserted is invoked.

    Warning

    By default, Delphi doesn't generate RTTI for non-published methods. That's why you must add the directive {$RTTI EXPLICIT METHODS([vcPrivate..vcPublished])} to your class. If you don't do that, Aurelius won't know about the mentioned methods and they will not be invoked when the events are triggered!

    Note that you can use the same method to handle more than one event. The method AfterModification will be invoked when event OnUpdated is fired, and also when OnInserted is fired.

    Finally, you can use two different signatures for the methods: the method can receive a single Args parameters of the type of the event (see the available events below).

    Alternatively, you can declare the method without specifying any parameter. This is useful if you don't need any information from event arguments and you want to keep your class as clean as possible (no dependency on a specific event type).

    Available events

    OnInserting Event

    Occurs right before an entity is inserted (create) in the database. Note that the event is fired for every entity that is about to be inserted. For example, a single Manager.Save call might cause several entities to be inserted, due to cascades defined in the associations. In this case the event will be fired multiple times, one for each saved entity, even when the developer only called Save once.

    Example:

    TMappingExplorer.Default.Events.OnInserting.Subscribe(
      procedure(Args: TInsertingArgs)
      begin
        // code here
      end
    );
    

    TInsertingArgs Properties

    Name Description
    Manager: TBaseObjectManager The TObjectManager object which fired the event.
    Entity: TObject The entity about to be inserted.
    Master: TMasterObjectValue The parent object of the object being inserted. This property comes with a value in the case of list items (ManyValuedAssociation) that don't have a reference back to parent (unidirectional). TMasterObjectValue has two relevant properties: "MasterObject" which is the instance of parent object, and "MasterAssocMember" which is the name of the list property the item being inserted belongs to (for example, "InvoiceItems").

    OnInserted Event

    Occurs right after an entity is inserted (create) in the database. Note that the event is fired for every entity inserted. For example, a single Manager.Save call might cause several entities to be inserted, due to cascades defined in the associations. In this case the event will be fired multiple times, one for each saved entity, even when the developer only called Save once.

    Example:

    TMappingExplorer.Default.Events.OnInserted.Subscribe(
      procedure(Args: TInsertedArgs)
      begin
        // code here
      end
    );
    

    TInsertedArgs Properties

    Name Description
    Manager: TBaseObjectManager The TObjectManager object which fired the event.
    Entity: TObject The entity that was inserted.
    Master: TMasterObjectValue The parent object of the object being inserted. This property comes with a value in the case of list items (ManyValuedAssociation) that don't have a reference back to parent (unidirectional). TMasterObjectValue has two relevant properties: "MasterObject" which is the instance of parent object, and "MasterAssocMember" which is the name of the list property the item being inserted belongs to (for example, "InvoiceItems").

    OnUpdating Event

    Occurs right before an entity is about to be updated in the database.

    Example:

    TMappingExplorer.Default.Events.OnUpdating.Subscribe(
      procedure(Args: TUpdatingArgs)
      begin
        // code here
      end
    );
    

    TUpdatingArgs Properties

    Name Description
    Manager: TBaseObjectManager The TObjectManager object which fired the event.
    Entity: TObject The entity that is going to be updated.
    OldColumnValues: TDictionary<string, Variant> Represents the old object state using column name/value pairs. Don't confuse it with property names/values. For example, if the object has a property named "Name" that is mapped to a column database "CUSTOMER_NAME", the dictionary will contain "CUSTOMER_NAME" in the string key, and the respective value. Thus, associations are also represented by the foreign key column names/values.
    NewColumnValues: TDictionary<string, Variant> Same as OldColumnValues, but contains the new state values. Comparing what has changed between NewColumnValues and OldColumnValues will give you the names of the columns that will be updated in the database.
    ChangedColumnNames: TList<string> Contains a list of names of all columns that will be updated in the UPDATE statement.
    RecalculateState: Boolean If you have changed any property value of the entity that is about to be updated, you need to set RecalculateState to True to force Aurelius to recalculate the columns that were modified and update the object state in the manager cache. For better performance, leave it false if you haven't modified any property.

    OnUpdated Event

    Occurs right after an entity is updated in the database.

    Example:

    TMappingExplorer.Default.Events.OnUpdated.Subscribe(
      procedure(Args: TUpdatedArgs)
      begin
        // code here
      end
    );
    

    TUpdatedArgs Properties

    Name Description
    Manager: TBaseObjectManager The TObjectManager object which fired the event.
    Entity: TObject The entity that was updated.
    OldColumnValues: TDictionary<string, Variant> Represents the old object state using column name/value pairs. Don't confuse it with property names/values. For example, if the object has a property named "Name" that is mapped to a column database "CUSTOMER_NAME", the dictionary will contain "CUSTOMER_NAME" in the string key, and the respective value. Thus, associations are also represented by the foreign key column names/values.
    NewColumnValues: TDictionary<string, Variant> Same as OldColumnValues, but contains the new state values. Comparing what has changed between NewColumnValues and OldColumnValues will give you the names of the columns that will be updated in the database.
    ChangedColumnNames: TList<string> Contains a list of names of all columns that were updated in the UPDATE statement.

    OnDeleting Event

    Occurs right before an entity is about to be deleted from the database. Note that the event is fired for every entity deleted. For example, a single Manager.Remove call might cause several entities to be deleted, due to cascades defined in the associations. In this case the event will be fired multiple times, one for each deleted entity, even when the developer only called Remove once.

    Example:

    TMappingExplorer.Default.Events.OnDeleting.Subscribe(
      procedure(Args: TDeletingArgs)
      begin
        // code here
      end
    );
    

    TDeletingArgs Properties

    Name Description
    Manager: TBaseObjectManager The TObjectManager object which fired the event.
    Entity: TObject The entity about to be deleted.

    OnDeleted Event

    Occurs right after an entity is deleted from the database. Note that the event is fired for every entity deleted. For example, a single Manager.Remove call might cause several entities to be deleted, due to cascades defined in the associations. In this case the event will be fired multiple times, one for each deleted entity, even when the developer only called Remove once.

    When the event is fired, the entity object is still a valid reference, but will be destroyed right after the event listener returns.

    Example:

    TMappingExplorer.Default.Events.OnDeleted.Subscribe(
      procedure(Args: TDeletedArgs)
      begin
        // code here
      end
    );
    

    TDeletedArgs Properties

    Name Description
    Manager: TBaseObjectManager The TObjectManager object which fired the event.
    Entity: TObject The deleted entity.

    OnCollectionItemAdded Event

    Occurs when an item is added to a collection, at database level. In other words, when the foreign key of an item entity is set to point to the parent entity.

    Example:

    TMappingExplorer.Default.Events.OnCollectionItemAdded.Subscribe(
      procedure(Args: TCollectionItemAddedArgs)
      begin
        // code here
      end
    );
    

    TCollectionItemAddedArgs Properties

    Name Description
    Manager: TBaseObjectManager The TObjectManager object which fired the event.
    Parent: TObject The parent entity which contains the collection where the item was added to.
    Item: TObject The item entity added to the collection.
    MemberName: string The member name (field or property) of the parent entity that holds the collection.

    OnCollectionItemRemoved Event

    Occurs when an item is removed from a collection, at database level. In other words, when the foreign key of an item entity is set to null (or to a different parent entity).

    Example:

    TMappingExplorer.Default.Events.OnCollectionItemRemoved.Subscribe(
      procedure(Args: TCollectionItemRemovedArgs)
      begin
        // code here
      end
    );
    

    TCollectionItemRemovedArgs Properties

    Name Description
    Manager: TBaseObjectManager The TObjectManager object which fired the event.
    Parent: TObject The parent entity which contains the collection where the item was removed from.
    Item: TObject The item entity removed from the collection.
    MemberName: string The member name (field or property) of the parent entity that holds the collection.

    OnSqlExecuting Event

    Occurs right before an SQL statement is executed.

    Example:

    TMappingExplorer.Default.Events.OnSqlExecuting.Subscribe(
      procedure(Args: TSQLExecutingArgs)
      begin
        // code here
      end
    );
    

    TSQLExecutingArgs Properties

    Name Description
    SQL: string The SQL statement that will be executed.
    Params: TEnumerable<TDBParam> A list of TDBParam objects used for the SQL statement execution. The TDBParam object has the properties ParamName, ParamType and ParamValue.
    In This Article
    Back to top TMS Aurelius v5.11
    © 2002 - 2022 tmssoftware.com