web
You’re offline. This is a read only version of the page.
close
Skip to main content

Notifications

Announcements

No record found.

Community site session details

Community site session details

Session Id :
Microsoft Dynamics AX (Archived)

update on table buffer is not working after 'buf 2con' 'con2buf'

(0) ShareShare
ReportReport
Posted on by

Hello,
I want to convert an buffer into a container and for this I used buf2con() function. Then I use this container for a second buffer with the con2buf() function.
Now I want change some values and write the data back to the database using the update() function. But it is not working. No error message, no exception, just nothing happened. An insert() worked. Any suggestions?

Here is my example

{
    MyTable        buf1;
    MyTable        buf2;
    container      c;
    str 10         keyId = "1";
    ;
    
    buf1.KeyId  = keyId;
    buf1.Text   = "Hello World";
    buf1.insert();

    select * from buf1 where buf1.KeyId == keyId;
    
    c = buf2con(buf1);
    
    con2buf(c, buf2);

    if(buf2)
    {
        buf2.selectForUpdate(true);
        ttsbegin;
        buf2.Text = "Hello! Need Help :)";
        buf2.update();
        ttscommit;
    }

    //reread buf1 but the value of field 'text' is still 'Hello World'
    select * from buf1 where buf1.KeyId == keyId;
    info(buf1.Text);
}


*This post is locked for comments

I have the same question (0)
  • AX 2012 r3 Profile Picture
    2,426 on at

    1.You are Updating Buf2.Text

    (

    buf2.selectForUpdate(true);

           ttsbegin;

           buf2.Text = "Hello! Need Help :)";

           buf2.update();

           ttscommit;

    )

    2.At last you are printing Buf1.Text.

    (

     select * from buf1 where buf1.KeyId == keyId;

       info(buf1.Text);

    )

    3.you are not again Updating Buf1.Text.

    4.With out Updating in Buf1 how can changes get reflected.

  • Verified answer
    Martin Dráb Profile Picture
    237,801 Most Valuable Professional on at

    It shouldn't work, although I would expect an exception at runtime.

    You can't update buf2, because you never selected it. Calling selectForUpdate(true) merely says that the next select should be with the "for update" flag, but there is no subsequent select.

  • Matthias Ulbricht Profile Picture
    on at

    Hello,
    the requirement is that we have built a website which is managed by AX (via business connector). For this reason we have a state machine in AX which controls the process and serializes the required data. I have extended all required classes with pack and unpack functions. In this way, all table buffers are also packed into a container and written to the database as a session with the rest of the data. If the user then enters a message on the web page, the session in AX is then restored and processed.
    This works well except for the update.
    And we wanted to avoid reloading all data records from the database again for performance reasons.

    After some trial and error I found another solution today.  If you call the data () function with the same buffer after con2buf (), the update () works afterwards. I don't know why.

    con2buf(c, buf2);
    buf2.data(buf2);


  • Suggested answer
    Vilmos Kintera Profile Picture
    46,149 on at

    You are not using the con2buf correctly, it is an empty buffer. Check the documentation, it has a record return type (Common).

    https://msdn.microsoft.com/en-us/library/global.con2buf.aspx

    https://blogs.msdn.microsoft.com/axperf/2011/09/07/improvements-on-the-global-methods-buf2con-and-con2buf-in-microsoft-dynamics-ax-2012/

    So your line should look like this:

    buf2 = con2buf(c);


    No second parameter is required to determine the return type, since that is already available in the packed buffer. This way a new record is created.

    If you intend to replace the value in just the variable, then you do not need a TTS block and an update, just a value assignment.

    If you intend to update the record in the DB too, then your approach again is incorrect, and you must select the buffer from the DB first running a select statement on buf2 based on the unique identifiers, then you could do the whole TTS/update steps.

  • Matthias Ulbricht Profile Picture
    on at

    Hello, Vilmos,

    thanks for your hint, but the function con2Buf () has no return value. At least not in AX2009.

    static void con2Buf(container c,
                        Common    common)
    {
        fieldId   fieldId;
        int       i;
        DictTable dictTable;
    
        if (common.TableId == conpeek(c,1))
        {
            dictTable = new DictTable(common.TableId);
            fieldId = dictTable.fieldNext(0);
            i = 2;
            while (fieldId)
            {
                common.(fieldId) = conpeek(c,i);
                i++;
                fieldId = dictTable.fieldNext(fieldId);
            }
        }
    }

    In my opinion, the use of con2Buf () was correct.

    With the rest you will probably be right and the buffer needs to be reloaded.

  • Vilmos Kintera Profile Picture
    46,149 on at

    It looks different in AX 2012 indeed, did not know that. You may notice how they use makeRecord to create a new empty buffer.

    You may implement your version using that code if you want, like con2buf2012.

    static Common con2Buf(container _container,
                          Common    _rec = null)
    {
        Common    thisRec = null;
        TableId   tableId;
        DictTable dictTable;
        FieldId   fieldId;
        int       i;
        boolean   convert = false;
    
        if ( prmisDefault(_rec) )
        {
            tableId   = conPeek(_container,1);
            dictTable = new DictTable(tableId);
    
            if (dictTable)
            {
                thisRec = dictTable.makeRecord();
                convert = true;
            }
        }
        else
        {
            thisRec = _rec;
        }
    
        if(Types::Container == typeOf(conPeek(_container, conLen(_container))))
        {
            // delegate to kernel API
            thisRec.con2buf(_container);
        }
        else
        {
            // backward compatibility: unpack container packed with previous versions of AX
            tableId = conPeek(_container,1);
            dictTable = new DictTable(tableId);
    
            if(dictTable)
            {
                if (convert || tableName2id(_rec.getInstanceRelationType()) == tableId || _rec.TableId == tableId)
                {
                    fieldId = dictTable.fieldNext(0, TableScope::IncludeBaseTables);
                    i = 2;
                    while (fieldId)
                    {
                        thisRec.(fieldId) = conPeek(_container,i);
                        i++;
                        fieldId = dictTable.fieldNext(fieldId, TableScope::IncludeBaseTables);
                    }
                }
            }
        }
    
        return thisRec;
    }
    
  • Vilmos Kintera Profile Picture
    46,149 on at

    Please kindly mark the answers which you have found to be helpful with the checkbox next to each post, in order to resolve the thread and assist others.

  • Suggested answer
    Matthias Ulbricht Profile Picture
    on at

    Hello, Vilmos,

    also the AX2012 variant of the function con2Buf () does not work as expected. So I think Martin Drab is right and the update () is causing problems because the record was never selected.
    As I wrote before, it is only a little bit surprising that after the call

    buf2.data(buf2);

    the update () worked. But since I didn't find any documentation about what exactly is done by the system in the function data (Common _cursor), I can't judge if there is a problem with the unselected data set or if there is a bug. But it should be usable as a workaround.

  • Suggested answer
    Vilmos Kintera Profile Picture
    46,149 on at

    Again, you are trying to update an uninitialized buffer. Calling the data method does the initialization.

    You could simply remove your new line with the data assignment, and instead of update, call write() on the buffer. Then place a breakpoint both in the overridden insert and update method, and you will see what we have meant. It will stop the debugger in the insert method, since update operation only works for EXISTING record that is already SELECTED.

Under review

Thank you for your reply! To ensure a great experience for everyone, your content is awaiting approval by our Community Managers. Please check back later.

Helpful resources

Quick Links

Responsible AI policies

As AI tools become more common, we’re introducing a Responsible AI Use…

Neeraj Kumar – Community Spotlight

We are honored to recognize Neeraj Kumar as our Community Spotlight honoree for…

Leaderboard > 🔒一 Microsoft Dynamics AX (Archived)

#1
Martin Dráb Profile Picture

Martin Dráb 4 Most Valuable Professional

#1
Priya_K Profile Picture

Priya_K 4

#3
MyDynamicsNAV Profile Picture

MyDynamicsNAV 2

Last 30 days Overall leaderboard

Featured topics

Product updates

Dynamics 365 release plans