Attain: OnGlobal Triggers in CU 1

TorbenTorben Member Posts: 21
Hi all

How sad I was to realize that the OnGlobal triggers in CU 1 only are run when logging is enabled! :shock:

I need to call a specific CU for replication purposes, each time a user inserts/modifies or deletes a record in any table in the database.
So far I have been entering code on each and every table (almost) in the database.

There must be a way to obtain control or to trick Attain to execute the looong awaited OnGlobal Triggers. Without having the customer to buy Logging.

Any ideas?

Tnx
Torben

Comments

  • UrmasUrmas Member Posts: 76
    Off-course there is a way - you just have to crack open the Private Key MSBS is using to sign the licenses. ;-)

    I seriously think that the buying of the logging functionality costs far less for your customer ;-)
  • TorbenTorben Member Posts: 21
    Prob is that most of our customers have a lot of locations (20-50) which then each have to by Logging. And thats quite a sum of money.
    And it would be a much more neat soultion to use the OnGlobal triggers... _if_ they worked as expected...

    :(

    Best rgds
  • jreynoldsjreynolds Member Posts: 175
    The firing of the global triggers in CU 1 is controlled by the GetGlobalTableTriggerMask function (also in CU 1). The default behavior of this function is to use data from the change log setup, but this could be modified to use any data and logic that you desire.
  • UrmasUrmas Member Posts: 76
    Oops, you ar correct - seems that the licence crack was not needed at all.

    Going now to rewrite part of my own code...
  • TorbenTorben Member Posts: 21
    Yes - I have tried to put code on the GetGlobalTableTriggerMask trigger.

    But when is this trigger fired? It seems that it is only fired the first time that data in a table is written to the database...i.e. changing several items only fires the trigger the first time...

    And I need the trigger to be fired each time a write to the db is executed.

    Any more suggestions?

    Best rgds
  • jreynoldsjreynolds Member Posts: 175
    I'm not 100% certain how it works, but my experimentation leads me to believe that GetGlobalTableTriggerMask is fired the first time a change is made to a table. The result of the function is maintained within CU 1 until it is cleared (CU 1 behaves a lot like a single instance codeunit so it is cleared when the current company is closed).

    So basically what happens is when the first change is made to a table GetGlobalTableTriggerMask fires and returns a result. Based on that result and the action that is causing the change to the table (INSERT, MODIFY, DELETE, or RENAME) the appropriate global trigger may fire. Subsequent changes to the table do not cause GetGlobalTableTriggerMask to fire as the previous result for that table is know and can be used to determine if the appropriate global trigger should fire. Once the company is closed, CU 1 is cleared, and so the next change to the table will cause GetGlobalTableTriggerMask to fire again. Changes to other tables cause similar behavior for the first and subsequent changes to those tables as well.

    Therefore, if you have made changes to the setup data that GetGlobalTableTriggerMask uses to determine which global triggers to fire for which tables, then it may be necessary to close the current company before those changes are recognized.
  • JJ Member Posts: 10
    To always have the OnGlobal... triggers get fired in Navision you could do the following:

    In the GetGlobalTableTriggerMask you would have to change the original code.
    EXIT(15); // This triggers all OnGlobal... events
    

    Now comes the tricky part in the OnGlobal... triggers you should test if logging is enabled for the Log Management module. However, if you are sure your customer won't ever buy a license for it you could just remove the original code.

    Now all you have to do is write your own implementation for these triggers.

    Please note that the OnGlobal... triggers are only executed when an Insert, Modify or Delete is called with the RunTrigger parameter set to TRUE. When one of these functions is called without the RunTrigger parameter these OnGlobal... triggers will NOT be executed.

    Also remember this is for every table (including the object table) in the database, so you may want to write some code testing what record you are logging, because object table might not be that interesting to your customer.

    This should give you all the flexibility you need. By setting the return value of the GetGlobalTableTriggerMask to 15 we have told Navision we want to Run all the OnGlobal... triggers.
  • TorbenTorben Member Posts: 21
    Exit(15)... This seems to work and to solve my problem!!! :D The binary representation af 15 is 1111, where each "1" digit controls one OnGlobaltrigger (Ind,Mod,Del,ren)
    This is great!

    This will now be subject for further investigation!

    Thx for the feedback 8)
  • TorbenTorben Member Posts: 21
    Disaster... :shock:

    Seems that the RunTrigger parameter does NOT fire the OnGlobal
    triggers!

    Ex a codeunit with the following statement
    ItemRec.MODIFY(True);
    ...does not fire the OnGlobal triggers... :cry:

    But any manual modification of the Item card does fire the OnGlobal...triggers OK....

    ...help...
  • UrmasUrmas Member Posts: 76
    In fact it makes a lot of sense. You can trap the modifications in code yourself (by adding code) if needed. It would be quite disaster for a perfomance if for every change in DB would call a trigger running in the client computer. It would be a real "killer app" for SQL ;-)
  • Peter_WijntjesPeter_Wijntjes Member Posts: 28
    :twisted: Actually the 2 tier client server architecture of MBS Navision causes this "sens-making" behaviour. From a functional point of view it actually does make a lot of sense to trap every modification.

    To accomplish this you need to write triggers in SQLServer, because an Insert(FALSE) / Modify(FALSE) will never make it to any validation trigger... ](*,)
    Peter Wijntjes
    MBS NAV Consultant
  • JJ Member Posts: 10
    This behaviour also surprises me. Since you would want to track every change made to the database.

    In the architecture of Navision it is obvious that an Insert, Modify or Delete with the RunTrigger parameter set to FALSE the database is altered without any intervention from the client (it is the absolute fastest way to insert data).

    However when the RunTrigger is set to TRUE you should expect these OnGlobal events to also be executed. The RunTrigger is called for a reason. Trapping every change through the individual tables cannot be the way to go ... It means the developer has to code every single table ...

    In my opinion a design error within MBS Navision. #-o
  • TorbenTorben Member Posts: 21
    :shock: :cry:
  • UrmasUrmas Member Posts: 76
    Sorry for silly question - just trying to widen my view on world out there

    Why do you want to track ALL changes - even those what are made by Navision itself?
    I understand manual change tracking - people do mistakes. I do understand debugging - programmers do mistakes, but why to track everything in production system?
  • TorbenTorben Member Posts: 21
    The answer is replication...I have a bunch of individual stores over some distances that need to replicate f.x. posted entries to headquater, and a headquater that needs to replikate f.x. item information to stores.

    Okay...I don't need all tables to be replicated, but still a lot. :wink:
    Thx for the interest
  • JJ Member Posts: 10
    To be able to track things on a high level you must be able to catch the events on that higher level ... If you cannot not intervene on this level it means you will have to write code everywhere ...

    As a programmer I would like to grab the event at a higher level and then decide what to do.

    There are many reason for wanting this ... An example would be to update a SQL database with a new order once it is added in Navision so the Customer can see his order when he goes online. A sales order consists of more than 1 table and this means that the code you need write is in many places.

    I personally do not like to write similar code in many different places when the code is basically the same. Intervening at a higher level means you have more flexibility.

    Changes are easier to make since you do not have to go through many different pieces of code and therefore reduces the risk of creating bugs in you code because you changed something in 1 place but forgot that there are 5 more places to make the same change ...
  • TorbenTorben Member Posts: 21
    I agree...

    I hoped to solve this replication task by catching the OnGlobal Triggers. But this now seems nothing but a naive dream :(

    So...Back to square one. I still have to enter code on every table that I need to be replicated.

    So close...
  • janpieterjanpieter Member Posts: 298
    SQL server may have triggers that you need.

    But also SQL server can do replication.


    But then, yeah it think the global triggers suck. I wanted to make a "Last modified Date-Time" field on some tables and there was just not a way to effectively populate this field when a record changes ... I have been trying the global triggers thinking that was a sollution but it wasn't.

    The only think you can do then is fill the field in every onmodify trigger but then you must be sure that every modify is called with TRUE. That is almost impossible.
    In a world without Borders or Fences, who needs Windows and Gates?
  • WaldoWaldo Member Posts: 3,412
    Urmas wrote:
    Sorry for silly question - just trying to widen my view on world out there

    Why do you want to track ALL changes - even those what are made by Navision itself?
    I understand manual change tracking - people do mistakes. I do understand debugging - programmers do mistakes, but why to track everything in production system?
    For interface reasons...


    Does anyone have a solid solution for this yet?

    Eric Wauters
    MVP - Microsoft Dynamics NAV
    My blog
  • jordi79jordi79 Member Posts: 275
    I think it was changed to log only user changes to log all changes incl. system changes, so that it can integrate to other system. I think they made this change to integrate to MS CRM.

    But yes, I agree that maybe it was better if we can differentiate in change log if the change is a user change or a system change.
Sign In or Register to comment.