Skip to main content

Notifications

Finance | Project Operations, Human Resources, ...
Unanswered

Handling errors and updating tables when using recordInsertList

(0) ShareShare
ReportReport
Posted on by 1,550
Hi,

I have this service class, and i want to enhance the code performance and also start using RecordInsertList when inserting to TableX but I'm not sure what to do with updateTableASuccess and updateTableAFail

Here's the current Code, and i'll show u after it, what I tried to do in order to enhance it with RecordInsertList (but i don't know what i will do with parmTable and updateTableASuccess and updateTableAFail)
 
 public service()
{
    public void process(ContractA _contract)
    {
        System.Exception ex;
        query    = _contract.getQuery();
        queryRun = new QueryRun(query);
        while(queryRun.next())
        {
            
            table1 =   queryRun.get(tableNum(Table1));
            table2 =   queryRun.get(tableNum(Table2));
            if(table2) 
            {                
                try
                {
                    ttsbegin;
                    ClassA classA = ClassA::newFromfieldA(table1.Field1Enum);
                    if(classA)
                    {
                        classA.run(table2);
                        this.updateTableASuccess(table2, classA.parmTable());
                    }
                    else
                    {
                        throw error(/error/);
                    }
                    ttscommit;
                }
                catch(ex)
                {
                    this.updateTableAFail(tableA, ex.Message);
                }
            }
        }       
    }
    
 
    public  void updateTableASuccess(Table2 _table2, common _table)
    {
        ttsbegin;
        _table2.selectForUpdate(true);
        _table2.RefTableId = _table.TableId;
        _table2.RefRecId   = _table.RecId;

        _table2.Status     = Status::Completed;
        _table2.ErrorTxt   = '';
        _table2.update();
        ttscommit;
    }

    public  void updateTableAFail(Table2 _table2, str _errorMsg)
    {
        ttsbegin;
        _table2.selectForUpdate(true);
        _table2.ErrorTxt = _errorMsg;
        _table2.Status   = Status::Error;
        _table2.update();
        ttscommit;
    }
}

 
[EnumAtrribute (Field1Enum::Value1)]
class class1 extends ClassA
{

    protected void process(str _name)
    {
           //logic
           ttsbegin;
           TableX tableX = TableX ::find(x,y);
           if(!tableX )
           {
                 tableX.X= x;
                 tableX.Y= y;
                 tableX .Name = _name;
                 tableX.insert();
            }
            else
            {
                 tableX.selectForUpdate(true);
                 tableX.Name = _name;
                 tableX.update();
             }
 
            this.parmTable(tableX );
            ttscommit;
}

As you can see, when inserting records in TableX in class1  -- I'm updating table2 in case of errors and Success  -- not sure how to handle this in the new code below after using recrodInsertList as i won't have the recId yet
---------------------------------------------------------------------------------
Here's my new code:
 
 public service()
{
    public void process(ContractA _contract)
    {
        System.Exception ex;
        query    = _contract.getQuery();
        queryRun = new QueryRun(query);

        ClassA classA; 
        Map map  = new Map(Types::Enum, Types::Class);
 
        while(queryRun.next())
        {
            
            table1 =   queryRun.get(tableNum(Table1));
            table2 =   queryRun.get(tableNum(Table2));
            if(table2) 
            {                
                try
                {
                    ttsbegin;
                    if(map.exists(table1.Field1Enum))
                    {
                        classA= map.lookup(table1.Field1Enum);
                    }
                    else
                    {
                        classA= CassA::newFromfieldA(table1.Field1Enum);
                        map.add(table1.Field1Enum, classA);
                    }

                    if(classA)
                    {
                        classA.run(table2);
                        this.updateTableASuccess(table2, classA.parmTable());  // what I'm going to do with this after i used insertRecordList
                    }
                    else
                    {
                        throw error(/error/);
                    }
                    ttscommit;
                }
                catch(ex)
                {
                    this.updateTableAFail(tableA, ex.Message);  // what I'm going to do with this after i used insertRecordList
                }
            }
        }
 
        MapEnumerator mapEnum = map.getEnumerator();
        while (mapEnum .moveNext())
        {
            classA= mapEnum .currentValue();
            if (classA)
            {
                classA.InsertToDatabase();
            }
        }
 
    public  void updateTableASuccess(Table2 _table2, common _table)
    {
        ttsbegin;
        _table2.selectForUpdate(true);
        _table2.RefTableId = _table.TableId;     //what to do 
        _table2.RefRecId   = _table.RecId;

        _table2.Status     = Status::Completed;
        _table2.ErrorTxt   = '';
        _table2.update();
        ttscommit;
    }

    public  void updateTableAFail(Table2 _table2, str _errorMsg)
    {
        ttsbegin;
        _table2.selectForUpdate(true);      //what to do 
        _table2.ErrorTxt = _errorMsg;
        _table2.Status   = Status::Error;
        _table2.update();
        ttscommit;
    }
       
    }
 
}

 
[EnumAtrribute (Field1Enum::Value1)]
class class1 extends ClassA
{
    RecordInsertList    recordList = new RecordInsertList(tableNum(TableX));

    protected void process(str _name)
    {
           //logic
           ttsbegin;
           TableX tableX = TableX ::find(x,y);
           if(!tableX )
           {
                 tableX.X= x;
                 tableX.Y= y;
                 tableX .Name = _name;
                 recordList.add(tableX);
            }
            else
            {
                 tableX.selectForUpdate(true);
                 tableX.Name = _name;
                 tableX.update();
             }
 
            this.parmTable(tableX );
            ttscommit;
    }
 
    public void InsertToDatabase()
    {
        recordList.insertDatabase();
    }
 
}
  • Martin Dráb Profile Picture
    Martin Dráb 230,934 Most Valuable Professional on at
    Handling errors and updating tables when using recordInsertList
    If it's true that you want to process them in bulk, they you must forget your logging, because that's based on the idea of processing records one by one.
     
    Regarding find(), you're referring to a wrong piece of information. The way of eliminating repeated calls of find() in a loop is using a join. So instead of fetching records from one table and call find() on other table for every record, you can use a join to get just records with a related record in the other table (for update) or without a related record (for insert). You know what a join is, don't you?
  • junior AX Profile Picture
    junior AX 1,550 on at
    Handling errors and updating tables when using recordInsertList
    Hi Martin,

    But recordInsertList is used for TableX... while loggin the status is for Table2 where i will need info from TableX.
    So i do want to process records in bulk for TableX​​​​​​​. It's the logging status what i'm not sure how to do. Any idea??

    Regarding this "You may still be able to utilize my optimization for not calling find() for every record"
    I'm not sure how u want me to pass
     the new query to Query::insert_recordset(). and what did u mean by i won't need to iterate query... can you please show me?

     
  • Martin Dráb Profile Picture
    Martin Dráb 230,934 Most Valuable Professional on at
    Handling errors and updating tables when using recordInsertList
    You can run some logic in insert() / update() methods or subscribe to events, but then you get no benefit from trying to use set-based processing, because then you must process them one by one and not sending several records to database at once.
     
    You need to decide whether you want to process records in bulk or one by one. If you must do it individually, there is no point in trying to use set-based processing (RecordInsertList, insert_recordset or anything like that).
     
    You may still be able to utilize my optimization for not calling find() for every record
  • junior AX Profile Picture
    junior AX 1,550 on at
    Handling errors and updating tables when using recordInsertList
    Hi Martin,
     
    If I'm going to use insertRecordSet, is there a way to log status for individual records? Like store them in a map maybe?
     
    If i'm going to use Query::insert_recordset() and Query::update_recordset() can u show me how to amend my code?..also how i'm going to log status? Can u show me please?
  • Martin Dráb Profile Picture
    Martin Dráb 230,934 Most Valuable Professional on at
    Handling errors and updating tables when using recordInsertList
    Sorry, I'm unable to say whether it would work without knowing what the "extra logic" does. In general, insert_recordset / update_recordset are used for quite straightforward field assignments, such as in your current code. But if you actually need something else, then it may easily be impossible with this design. As always, it's crucial to know requirements when designing a solution.
     
    Your methods for logging status of an individual records don't make much sense if you don't process records individually. What you should do with them depends on what you want to happen (here we run to business requirements again). You can throw them away, redesign them or decide that your new design isn't suitable for what you need.
  • junior AX Profile Picture
    junior AX 1,550 on at
    Handling errors and updating tables when using recordInsertList
    Hi Martin,
     
    Please note that the "process" method can have extra logic but I added the main logic.
    And i showed u that class1 extends classA, but there could be class2 as well that extends classA and it will insert to maybe two tables, instead of one table in the "process" method.

    Would still  Query::insert_recordset() and  Query::update_recordset() still work?? if yes, then can you please show me how will you amend the code for it to work as I can't still get it.

    And my main question is still not answered, what shall i do with [
    parmTable() and updateTableASuccess() and updateTableAFail()] if i'm going to use InsertRecordSet or Query::insert_recordSet?
    can you please explain more
  • Martin Dráb Profile Picture
    Martin Dráb 230,934 Most Valuable Professional on at
    Handling errors and updating tables when using recordInsertList
    Have you considered utilizing Query::insert_recordset() and Query::update_recorset() methods? For example, for insert_recordset, you'd take the query from the contract, added a non-exists join with TableX and passed the new query to Query::insert_recordset(). If you can use that, you don't need to iterate the query at all.
     
    And of course, the join will eliminate the extra call of TableX::find() that you run for every record returned from the query, but that's not specific to Query::insert_recordset(). You could use that to improve your current solution as well.
  • junior AX Profile Picture
    junior AX 1,550 on at
    Handling errors and updating tables when using recordInsertList
    Hi Martin,

    Class1 extends classA and process is called inside the run method.

    Here's classA
     
    abstract class ClassA extends ClassB
    {
        public static ClassA newFromFieldA(Enum _enum)
        {
            EnumAtrribute enumAtrribute = new EnumAtrribute(_enum);
            return SysExtensionAppClassFactory::getClassFromSysAttribute(classStr(ClassA), enumAtrribute);
        }
     
        public final void run(Table2 _table2)
        {
            this.parmTable2(_table2);
            this.process(_table2.Txt);
        }
    }
  • Martin Dráb Profile Picture
    Martin Dráb 230,934 Most Valuable Professional on at
    Handling errors and updating tables when using recordInsertList
    You showed us code of class1.process(), but you never call this method from process() method of the other class. There you call ClassA.run(), which accepts a table buffer, not a string. What code do you have there?

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

Announcing Our 2025 Season 1 Super Users!

A new season of Super Users has arrived, and we are so grateful for the daily…

Vahid Ghafarpour – Community Spotlight

We are excited to recognize Vahid Ghafarpour as our February 2025 Community…

Congratulations to the January Top 10 leaders!

Check out the January community rock stars...

Leaderboard

#1
André Arnaud de Calavon Profile Picture

André Arnaud de Cal... 292,111 Super User 2025 Season 1

#2
Martin Dráb Profile Picture

Martin Dráb 230,934 Most Valuable Professional

#3
nmaenpaa Profile Picture

nmaenpaa 101,156

Leaderboard

Product updates

Dynamics 365 release plans