Skip to main content

Command Palette

Search for a command to run...

Optimizing the D365FO & AX Database performance using RecordInsertList

Updated
4 min read
B
Developer exploring D365FO, Azure, and more. Sharing what I learn along the way.

Scenario:

As we work with data, we usually have a database. So, all the actions which we perform for customization should be in such a way that it should not impact the performance of the system. We should be very careful while writing any piece of code.

For example, if we are working on SSRS reports and if the data retrieved by report is huge. Let’s assume the report is a DP based, where we will have a query which accepts inputs from the user and retrieve the data as a report. Generally speaking, user wants the report to run within no time even the report has huge data. If it takes huge time to run, it would be frustrating right?

As a developer we can understand the scenario if it is a query where user gives input, then we will have the X Query classes like QueryRun, Query etc. We generally write the code here like below to get the data from the user input.

Let's assume I have a "query" which sets based on user input.

InventTable             inventTable;
InventTrans             inventTrans;
QueryRun                queryRun;
RecordInsertList        myTableTmpList;
MyTable                 myTable;

queryRun            = new QueryRun(query);

while(queryRun.next())
{
    
    inventTable = queryRun.get(tableNum(InventTable));
    inventTrans = queryRun.get(tableNum(InventTrans));
    
    myTable.clear();
    myTable.ItemId = inventTable.ItemId;
    myTable.PostedDate = inventTrans.DatePhysical;
    myTable.ItemCreatedDate  = any2Date(inventTable.CreatedDateTime);
    myTable.insert();

}   

This code looks good and perfect, but it will call the database for each insert which will actually impact the report performance. I mean if it has 10000 lines, it will call database for each insert. Right?

So, how to tackle this?

Also, in this particular scenario we only need to use Query builder classes which are actually slower than the normal select statement in X but performance should be improved. Also, we cannot use insert_recordset here. So, is there any way to call the database only once with all the data to insert?

Solution:

One best way is to use Query builder classes along with RecordInsertList.

So, what is RecordInsertList?

As the name suggests it makes all the records which are retrieved by while or query builder into a list and finally calls the database once for the bulk insert of data. In this way we can speed up the performance of database. Simply a kind of List class.

Below is the code which explains the functionality of this using only a while loop.

Just like a normal while select, we will select all the records where the invoice date range is between given from and to date. So whatever data is retrieved it is added as an element into list and finally the list will call the insertDatabase() method which will insert all the listed data at once to the table.

class testRecordInsertList
{
    public static void main(Args  _args)
    {
        ProjInvoiceJour         projInvoiceJour;
        RecordInsertList        myTableTmpList;
        MyTable                 myTable;
        
        //initiating the list with temp table buffer
        myTableTmpList = new RecordInsertList(tableNum(MyTable), false, false, false, false, false, myTable);
            
        while select InvoiceDate InvoiceId from projInvoiceJour 
            where projInvoiceJour.InvoiceDate >= _fromdate
                && projInvoiceJour.InvoiceDate <= _todate
            {
                myTable.InvDate = projInvoiceJour.InvoiceDate;
 	            myTable.Invoice = projInvoiceJour.InvoiceId;
                myTableTmpList.add(myTable);
            }
        myTableTmpList.insertDatabase();
    }
}

So, with this all the data is retrieved and made as a list for each record and finally will call database for insertion of all records as a list.

Below is the code where I am using Query classes with while.

Let’s assume that I have a complex query called “query” which sets based on user input. For demonstration purpose I only used 2 tables for the query.

The code will be as below.

InventTable             inventTable;
InventTrans             inventTrans;
QueryRun                queryRun;
RecordInsertList        myTableTmpList;
MyTable                 myTable;

queryRun            = new QueryRun(query);
myTableTmpList      = new RecordInsertList(MyTable), false, false, false, false, 
                    false, myTable);        

while(queryRun.next())
{
    
    inventTable = queryRun.get(tableNum(InventTable));
    inventTrans = queryRun.get(tableNum(InventTrans));
    
    myTable.clear();
    myTable.ItemId = inventTable.ItemId;
    myTable.PostedDate = inventTrans.DatePhysical;
    myTable.ItemCreatedDate  = any2Date(inventTable.CreatedDateTime);
    myTableTmpList.add(myTable);

}   
myTableTmpList.insertDatabase();

When compared to speed between normal insert() and RecordInsertList, there will be huge difference. RecordInsertList is much faster than insert().

This article is originally posted here.

Dynamics 365 Finance & Operations

Part 6 of 16

A comprehensive series of technical deep dives into D365FO development. From X++ coding standards to complex integrations and UI enhancements, this series provides battle-tested solutions for the modern consultant.

Up next

Multi Selection on a form by user and get selected records by X++ code

Context We might have scenario where we need to customize a form to add a button so that it should have multiselect capability and for example some functionality should happen on multi select like to

More from this blog

T

The Augmented Architect

17 posts

Welcome to a specialized technical hub for Dynamics 365 Finance & Operations. This blog moves beyond basic documentation to provide deep-dive X++ tutorials, battle-tested integration patterns, and architectural insights for the modern developer. From optimizing data entities and refining unbound form logic to implementing advanced warehouse and dispatch solutions, expect clean code and practical guidance from the front lines of global consulting. Let’s build more resilient enterprise application