Observer
By Nikolai L’Estrange, from TVision Technology Ltd. in the UK_
_
Abstract
Track all record changes against a defined table or set of tables.
Problem
Microsoft Dynamics NAV has the built in ability to track all record changes against any table, however it does not always fire the triggers for every table.
Solution
Create a setup table to define which other tables you want to track changes for, and optionally what triggers you want to fire, then link this up to the standard triggers in Codeunit 1.
Codeunit 1 Application Management contains the triggers OnDatabaseInsert, OnDatabaseModify, OnDatabaseDelete and OnDatabaseRename which are what we need to subscribe to in order to track record changes. However these triggers are only fired sometimes. This is determined by the parameters set in the function GetTableTriggerSetup, which is called once per table per session.
In order to define which tables we are interested in we can create a new table with the following fields:
**Observable Table:**
"Table ID" Integer Object.ID WHERE (Type=CONST(Table))
TrackInsert Boolean \[optional\]
TrackModify Boolean \[optional\]
TrackDelete Boolean \[optional\]
TrackRename Boolean \[optional\]
Then we can create a Codeunit that will set the Table Trigger Setup parameters and also subscribe to the OnDatabase triggers.
**LOCAL \[EventSubscriber\] GetTableTriggerSetup(TableId : Integer;VAR OnDatabaseInsert : Boolean;VAR OnDatabaseModify : Boolean;VAR OnDatabaseDelete : Boolean;VAR OnDatabaseRename : Boolean)**
IF Observable.GET(TableId) THEN BEGIN
IF Observable.TrackInsert THEN
OnDatabaseInsert := TRUE;
IF Observable.TrackModify THEN
OnDatabaseModify := TRUE;
IF Observable.TrackDelete THEN
OnDatabaseDelete := TRUE;
IF Observable.TrackRename THEN
OnDatabaseRename := TRUE;
END;
**LOCAL \[EventSubscriber\] OnDatabaseInsert(RecRef : RecordRef)**
IF Observable.Get(RecRef.NUMBER) AND Observable.TrackInsert THEN
//do something
**LOCAL \[EventSubscriber\] OnDatabaseModify(RecRef : RecordRef)**
IF Observable.Get(RecRef.NUMBER) AND Observable.TrackModify THEN
//do something
**LOCAL \[EventSubscriber\] OnDatabaseDelete(RecRef : RecordRef)**
IF Observable.Get(RecRef.NUMBER) AND Observable.TrackDelete THEN
//do something
**LOCAL \[EventSubscriber\] OnDatabaseRename(RecRef : RecordRef;xRecRef : RecordRef)**
IF Observable.Get(RecRef.NUMBER) AND Observable.TrackRename THEN
//do something
Note: In NAV2016 all these functions can be EventSubscribers that subscribe to the functions in Codeunit 1 as per above, in earlier versions of NAV these functions will need to be Global and called explicitly from within the Codeunit 1 functions.
NAV Usages
Variations of this pattern exists in the standard product in:
- Codeunit 423 Change Log Management
- Codeunit 5150 Integration Management. In this Codeunit the tables that fire triggers are hardcoded in C/AL.
Consequences
It is important that in our GetTableTriggerSetup function we only ever set the parameters to TRUE, and never set them to FALSE. This is because there may be other Codeunits listening to the triggers for that table, e.g. Change Log. This is also why we check the setup again within each trigger.
Related Topics
This pattern was originally described in the following blog:
https://geeknikolai.wordpress.com/2015/10/30/observer-pattern-in-dynamics-nav-2016/
NAV Versions
- From NAV 2016 use the code as shown
- For earlier versions see Note above