Update Primary Key and Modify the same rec....

SDSD Member Posts: 4
edited 2009-10-13 in Navision Attain
Hello all,

Is the following code valid in Navision?

RecA ponits to a Table with PK: Document Type, Document No, Line No.
RecB also points to the same table.

IF RecA.GET("Document Type"::Order,'123',10000) then begin
RecB := RecA;

RecB."Document Type" := RecB."Document Type"::Quote;
RecB."Document No." := '123';
RecB."Line No." := 0;

RecB.Modify;

End;

In other words, Can you modify a Rec, if you have updated the values in Primary key for the Rec all in the same routine/function?

Thanks.
-SD

Comments

  • DenSterDenSter Member Posts: 8,307
    No that doesn't work.

    If you want to change any primary key value, you must do a RENAME instead of MODIFY. In this case that would cause serious problems though, because you are trying to change an order line into a quote line. Without also creating a header for that line, you'd have no way of ever seeing your 'new' line.

    If your goal is to create a copy of your order lines as quote lines, you should use the copy document functionality. Create a new blank quote, click functions/copy document, and you should be able to browse to an order that you can copy.
  • SDSD Member Posts: 4
    Thanks for your reply. Document Type (Order / Quote) was used just as an example of PK. I basically wanted to know if the PK values update and Modify works together or not, you said it does not. Do you know what error message will it generate?

    Thanks,
    -SD.
  • DenSterDenSter Member Posts: 8,307
    This will generate an error saying
    The record does not exist.
    Identification fields and values:
    Document Type='Quote',Document No.=123,Line No.=0

    I would do something like this:
    IF RecA.GET("Document Type"::Order,'123',10000) THEN BEGIN
      RecB.INIT; // creates a new blank record
      RecB.TRANSFERFIELDS(RecA); //copies field values from RecA into RecB
      RecB."Document Type" := RecB."Document Type"::Quote;
        // Document No is already 123 from the TRANSFERFIELDS, 
        // so I dont have to set it here
      RecB."Line No." := 10000; // line numbers always start at 10000
      RecB.INSERT(TRUE); // it is a new record, so MODIFY won't work
    END;
    
  • SDSD Member Posts: 4
    Hi, Daniel:

    Your response is what I would recommend too ! I just wanted to confirm with another sr. developer like yourself, so that I know that I am NOT smoking ganja or something!! :roll:

    The problem is that we have several installations of Navision all across the world, every where else the same code does not give any problems but here in US we are getting an error message.

    Here is the code:
    Function : UpdateServiceItem(Var ServLine)

    IF ServLine."Service Item No." = '' THEN
    EXIT;

    IF Doc.GET(Doc."Document Type"::"Service Line",ServLine."Service Order No.",ServLine."Entry No.") THEN BEGIN
    DocModify := Doc;
    DocModify."Document Type" := DocModify."Document Type"::"Service Item ";
    DocModify."Document No." := ServLine."Service Item No.";
    DocModify."Document Line No." := 0;
    DocModify.MODIFY;
    END;

    here is the Error Message:

    "
    Another user has modified the record for this "name of the table" after you retrived from the database.
    Enter your changes again in the updated window, or start the interrupted activity again.

    Identification fields and values:

    Document Type='Service Item', Document No.='some no.', Document Line No. = '0'

    Notice that a GET is done on Doc, then copied to DocModify, but then PK values of DocModify are changed, and then an attempt to MODIFY the record is made. When I change the code to do exactly what you recommend, doing a TRANSFERFIELD(False) (so that the PK is not Initialized) and then update the PK values thru DocModify and INSERT. The error goes away, not a big surprise. But the question is how is it working in other databases? A Sr. developer in scandinivia is insisting that the code,as it is, is correct!!

    With Best Regards,
    -SD.
  • DenSterDenSter Member Posts: 8,307
    No that code is not correct. Taking a record, changing the primary key values and doing a MODIFY will simply not work. You MUST use RENAME, or create a new record.

    The reason you get the 'another user has modified...' error is that you GET the record in Rec, and then you try to modify it in RecModify. Navision thinks the one in Rec is still valid and throws an error when it tries to modify THAT one.

    If it were any non-primary key value I would not even copy the rec into another variable, and do something like:
    Function : UpdateServiceItem(Var ServLine)
    
    IF ServLine."Service Item No." = '' THEN
    EXIT;
    
    IF Doc.GET(Doc."Document Type"::"Service Line",ServLine."Service Order No.",ServLine."Entry No.") THEN BEGIN
      Doc."Document Type" := DocModify."Document Type"::"Service Item ";
      Doc."Document No." := ServLine."Service Item No.";
      Doc."Document Line No." := 0;
      Doc.MODIFY;
    END;
    
    Although I highly doubt that this code will work if the fields are indeed part of the primary key. There's just no reason to use a different variable when you're modifying an existing record. The 'another user...' error is because your Doc variable is not updated with the DocModify values, or because Navision is confused abiout how you can change a record that you didn't retrieve in the first place.

    By the way, if your code does not give you the "The record does not exist" error, then those fields are probably not part of the primary key.

    By the way 2, you don't need to do TRANSFERFIELD(FALSE), because FALSE is the default value.
  • KowaKowa Member Posts: 923
    Even though a RENAME is very slow and the TRANSFERFIELDS-INSERT (new record )-DELETE (old record) method is much faster, this has a big drawback : It does not update any tables with fields that have a table relation to this PK.
    Use it only if you are sure that none exist ( use the developers toolkit to check it ).
    Kai Kowalewski
  • DenSterDenSter Member Posts: 8,307
    Right that is a very good point if you need to delete the 'old' record. I was assuming he wants to make a copy of the record, since the MODIFY scenario doesn't make sense to me.
  • snyktpsnyktp Member Posts: 75
    Hi ,

    Even though a RENAME is very slow and the TRANSFERFIELDS-INSERT (new record )-DELETE (old record) method is much faster, this has a big drawback : It does not update any tables with fields that have a table relation to this PK.
    Use it only if you are sure that none exist ( use the developers toolkit to check it ).


    I cant use this for renaming "No." of customer table because it is related to many tables.. Am I wrong?

    Thank you
  • KowaKowa Member Posts: 923
    snyktp wrote:
    Hi ,

    Even though a RENAME is very slow and the TRANSFERFIELDS-INSERT (new record )-DELETE (old record) method is much faster, this has a big drawback : It does not update any tables with fields that have a table relation to this PK.
    Use it only if you are sure that none exist ( use the developers toolkit to check it ).


    I cant use this for renaming "No." of customer table because it is related to many tables.. Am I wrong?
    Don't even think of it. In this case you would not only miss the countless simple table relations, but the customer no. has conditional relations too (just one example, it acts as the Source No. in Item Ledger entries and Value entries which are created when sales are posted).
    Kai Kowalewski
Sign In or Register to comment.