Rollback without error

c.kestasc.kestas Member Posts: 15
Hi All,

Is there a way I can roll back a transaction without the use of an ERROR. I am looking, in other words, for the opposite of COMMIT?

Under cetrain circumstances, I need to rollback a transaction but continue processing other things. The ERROR statement will cause a rollback but would also halt execution too.

Thanks

Comments

  • Dennis_DecoeneDennis_Decoene Member Posts: 123
    :-k Mmm... Nope, no way

    Actually it's a common problem in Navision. There is no form of exception handling of any kind. This is a serious design mistake...

    Say when you want to write a new front end (such as scanner) wich sends messages to navision via the nas/msmq. You want to post a document. the posting fails. How do you send a message back to the scanner stating the problem???? ](*,)
  • Marije_BrummelMarije_Brummel Member, Moderators Design Patterns Posts: 4,262
    Can you use
    IF Codeunit.run then...
    

    If the codeunit fails (perhaps with error('')) you can continue with other code.
  • BeniHochBeniHoch Member Posts: 15
    I don't know if it helps you, but if you put the function which raise the Error into a Codeunit you can run this Codeunit und handle the value it returns:
    OK:= Codeunit.RUN(Record)
    
    No error message will be shown and the execution will continue. For the transaction the Help tell the following:
    The transaction that the codeunit contains is always committed due to the boolean return value.
    But for me it's not realy clear what happens with the transaction. :cry:
  • Marije_BrummelMarije_Brummel Member, Moderators Design Patterns Posts: 4,262
    Maybe it is woth a little test. I've never used it but it just poped up in my mind when I read this post.
  • DenSterDenSter Member Posts: 8,307
    Yes that is possible, I've used that to automatically attempt to post sales orders for instance. This program loops through a table of shipments, and attempts to post each one. If it is successful, the shipment is marked as 'processed' and when it it isn't it is marked as 'error'.

    Inside the loop I update the quantities to ship, and send the Sales Header into the posting routine, inside an IF statement. Simplified, the code looks like this:
    IF MyShipmentRecord.FIND('-') THEN REPEAT
      IF SalesPost.RUN(SalesHeader) THEN BEGIN
        // set the shipment to 'processed'
      END ELSE BEGIN
        // set the shipment to 'error'
      END;
    UNTIL MyShipmentRecord.NEXT = 0;
    
    If the posting routine fails, the loop is still alive and you can continue on on to the next record.
  • Bjarne_PedersenBjarne_Pedersen Member Posts: 1
    And if you want to save the error description from the codeunit, you can save an error message in a single instance codeunit, and get it after the codeunit returns an error.

    Of course this may demand a lot of programming, if it is a standard posting codeunit, but for something you make yourself, it is quite feasible.
  • DenSterDenSter Member Posts: 8,307
    Well that depends on which error message you are talking about. If it is a message that you build yourself in a text constant or a text variable, or even hard coded, then yes you can save that message in its own variable and retrieve that from the codeunit (and that does not have to be a single instance codeunit either), but you cannot save any standard Navision DBMS error message, that is simply not available in C/AL.
  • c.kestasc.kestas Member Posts: 15
    Thanks guys.

    Your replies have been very useful. I guess the answer is to call another codeunit for which I check the return value.

    Now if that codeunit terminates with an error, that error will never show. This is so because whenever the return code of a codeunit is checked, that codeunit gets automatically cleared before and after the call, so if it fails it simply dies and there is no way to return the reason afterwards.

    So, it does make sense to use a single - instance codeunit as a messenger for the error message.
  • DenSterDenSter Member Posts: 8,307
    No that's not how it goes. When a codeunit that is run using the return value errors out, it is not automatically cleared. You can still access its methods and global variables, except for the record variable that caused the error.

    So What I do is I create a global text variable called 'StatusMessage', and a function that returns its value. I set it to describe the next step, so that if the next step errors out, I can get the value of the message from the calling code.

    Let me give you an example. First I have a regular codeunit, with a global Item variable called Item and a global text variable called StatusMsg.
    OnRun(Rec = Item)
    StatusMsg := 'error validating Base Unit of Measure field';
    Item.VALIDATE("Base Unit of Measure",'WRONG VALUE');
    
    Now when you run this codeunit from the object designer, this would error out and the system would say something like "Item Unit of Measure does not exist. Values Item No=something, Unit of Measure Code='WRONG VALUE'". The Item variable would be destroyed at this point, so we can't tell any of its values. You can't catch the error itself, but you CAN use the value of the globals if you know how to do it.

    The codeunit also has a function called GetMessage, that returns the value of the StatusMsg variable.

    Now I declare my codeunit as a variable in another object, and I can evaluate the return value, and still access the global variable, like this:
    IF NOT MyCodeunit.RUN(MyItem) THEN BEGIN
      MESSAGE(MyCodeunit.GetMessage);
    END;
    

    So the codeunit errors out, but is still alive. All its variables are still there, except the one that caused the error.

    The only drawback is that you will never know what exactly went wrong. There is no way to catch the actual error message in Navision. I really hope this is one of the things we'll get in the new product so we don't have to rely on these types of tricks.
  • c.kestasc.kestas Member Posts: 15
    Thanks Daniel for taking the time to correct me.

    I tried it and it works as you describe. this behaviour however contradicts the online help that reads:

    If you include the return value, the system automatically clears the variables used in the codeunit object before and after it executes the object.

    Anyway, Thanks again.
  • Dennis_DecoeneDennis_Decoene Member Posts: 123
    Now that is fantastic. Thank you Denster. So stupid of me that I did not notice that you can catch the return value of the codeunit's run... :oops:

    The trick with setting the message first is allso brilliant in it's simplicity and effectivity.

    Thanks again,
  • DenSterDenSter Member Posts: 8,307
    Well thanks for the kind words :). It took a long time for me to figure this stuff out, and it really helped me out a lot. Don't feel stupid for not noticing somethint like that. Like Kestas says, the help even says that it clears the variables after executing. I didn't know that, I just tried it and it worked.
  • DakkonDakkon Member Posts: 192
    I used a similar approach for trapping errors. Luckily I didn't read that documentation so I had no idea that it shouldn't work that way ;)
    I guess ignorance really is bliss sometimes :)
    Thad Ryker
    I traded my sanity for a railgun :mrgreen:
  • Marije_BrummelMarije_Brummel Member, Moderators Design Patterns Posts: 4,262
    I just hope Navision will not fix this "bug" in the future. :D
  • DenSterDenSter Member Posts: 8,307
    Now there's a scary thought isn't it.... what if it really IS a bug.... [-o<
Sign In or Register to comment.