To execute a stored procedure from X++ use the Server method, the Client method does not have permissions. you don’t require any special privileges or permissions to execute a stored procedure. if used other then Server method, a message should appear like this Request for the permission of type SqlStatementExecutePermission failed.

public static void main(AssemblyLoadEventArgs _args)
    Connection con = new Connection();
    Statement stmt = new Con.createStatement();
    ResultSet r;
    str sql;
    SqlStatementExecutePermission perm;
    sql = stmt('EXEC [StoreprocedureName]');
    perm = new SqlStatementExecutePermission(sql);
    catch (Exception::Error)
        print "An error occured in the query";

Infographic Tiêu tiền khôn ngoan theo quy tắc 6 chiếc lọ

When creating new elements, ensure that you follow the recommended naming conventions. Any future development and maintenance will be much easier.

Ax Microsoft Dynamics AX typed data source

Axd Microsoft Dynamics AX business document

Asset Asset management

BOM Bill of material

COS Cost accounting

Cust Customer

Dir Directory, global address book

EcoRes Economic resources

HRM/HCM Human resources

Invent Inventory management

JMG Shop flor control

KM Knowledge management

Ledger General ledger

PBA Product builder

Prod Production

Proj Project

Purch Purchase

Req Requirements

Sales Sales

SMA Service management

SMM Sales and marketing management, also called customer relationship management (CRM)

Sys Application frameworks and development tools

Tax Tax engine

Vend Vendor

Web Web framework

WMS Warehouse management

Tip 1: Measure execution time of your code

Measuring is knowing. Before you start changing code, make sure you have a set of data you can keep reusing for your tests. Measure the performance of your code on that data after each change in code so you know the impact of your changes.

One way to do this is by using the Winapi::getTickCount() or WinApiServer::getTickCount() if your code runs on server method.

static void KlForTickCountSample(Args _args)
    int ticks;
    // get the tickcount before the process starts
    ticks = winapi::getTickCount();
    // start the process
    sleep(2000); // simulate 2 seconds of processing
    // compare tickcount
    ticks = winapi::getTickCount()  ticks;
    // display result
    info(strfmt('Number of ticks: %1', ticks));

Tip 2: limit the number of loops

A LOT of time goes into loops. If you have a performance problem, start looking for loops. Code can run really fast, but it can get slow when it is executed too many time, eg, in a loop.

Tip 3: avoid if in while select

When there is a if in a while select, see if you can rewrite it a a where statement in your select. Don’t be affraid use a join either. Consider the following example:

static void KlForIfInLoop(Args _args)
    VendTable vendTable;
    // usually slower
    while select vendTable
        if(vendTable.VendGroup == 'VG1')

    // usually faster
    while select vendTable
    where vendTable.VendGroup == 'VG1'

Tip 4: avoid double use of table methods

Using table methods a lot can get really slow if you do it wrong. Consider the following example:

static void klForTableMethodsSlow(Args _args)
    SalesLine salesLine;
    InventDim inventDim;
    // select a salesline
    select firstonly salesLine;
    inventDim.InventColorId = salesLine.inventDim().InventColorId;
    inventDim.InventSizeId  = salesLine.inventDim().InventSizeId;
    inventDim.inventBatchId = salesLine.inventDim().inventBatchId;

This example code looks nice, but there’s a problem. The salesLine.inventDim() method contains the following:

InventDim inventDim(boolean  _forUpdate = false)
    return InventDim::find(this.InventDimId, _forUpdate);

This means that the invendDim record is read three times from the database. It is better to declare the inventDim record locally and only retrieve it once:

static void klForTableMethodsFast(Args _args)
    SalesLine salesLine;
    InventDim inventDim;
    InventDim inventDimLoc;
    // select a salesline
    select firstonly salesLine;
    inventDimLoc = salesLine.inventDim();
    inventDim.InventColorId = inventDimLoc.InventColorId;
    inventDim.InventSizeId  = inventDimLoc.InventSizeId;
    inventDim.inventBatchId = inventDimLoc.inventBatchId;

Tip 5: Don’t put too much code on tables

Code on tables is usually fast, but things can get slow if you use it to much. Say you have a table with an InventDimId field. If you have 5 methods that need the InventDim record, because you don’t have a classDeclaration method on your table, you need to call this function 5 times, once in every method:


When you put these methods on a class, you could optimise it by fetching the record only once and storing it in the classDeclaration, or better, passing it as a parameter to your methods. An other example is fetching parameters from parameter tables, eg InventParameters::find(). On a table, you have to fetch it each time you call a method. In a class, you would probably optimize your code to only fetch the parameter record once.

Tip 6: Use the fastest code

For some tasks, there is special code that is faster than the code you would normally write. For example:

// slower
while select forupdate custTable
where custTable.custGroup == 'TST'
// faster
delete_from custTable
where custTable.custGroup == 'TST';

The same applies to update_recordset for updating records. Also, when adding values to the end of a container

cont += "a value";

is faster than

 cont = conins(cont, conlen(cont), "a value");

Tip 7: Every optimization counts

Remember that every optimization you do to you code counts, even if it’s a little one. Small performance tweaks can have a huge effect once you process large quantities of data. So don’t be lazy, and optimize.

Share from

In this post let’s explore creating XML using X++ code in Dynamics AX.

The following example shows how to create and write data to an XML file by using the XmlDocument, XmlElement, and XmlWriter classes. It loops through all of the records in the CarTable and find all the fields in the table automatically by using the DictTable and DictField classes.

static void WriteXml(Args _args)

    XmlDocument xmlDoc;
    XmlElement xmlRoot;
    XmlElement xmlField;
    XmlElement xmlRecord;
    XMLWriter xmlWriter;

    CarTable carTable;
    DictTable dTable = new DictTable(tablenum(CarTable));
    DictField dField;
    int i, fieldId;
    str value;


    // Create a new object of the XmlDocument class
    xmlDoc = XmlDocument::newBlank();

    // Create the root node
    xmlRoot = xmlDoc.createElement(#CarRootNode);

    // Loop through all the records in the carTable
    while select carTable
        // Create a XmlElement (record) to hold the
        // contents of the current record.
        xmlRecord = xmlDoc.createElement(#CarRecords);
        // Loop through all the fields in the record

        for (i=1; i<=dTable.fieldCnt(); i++)
            // Get the fieldId from the field-count
            fieldId = dTable.fieldCnt2Id(i);
            // Find the DictField object that matches the fieldId
            dField = dTable.fieldObject(fieldId);
            // Skip system fields
            if (dField.isSystem())

            // Create a new XmlElement (field) and
            // have the name equal to the name of the
            // dictField
            xmlField = xmlDoc.createElement(;
            // Convert values to string. I have just added
            // a couple of conversion as an example.
            // Use tableName.(fieldId) instead of fieldname
            // to get the content of the field.
            switch (dField.baseType())
                case Types::Int64 :
                    value = int642str(carTable.(fieldId));
                case Types::Integer :
                    value = int2str(carTable.(fieldId));
                default :
                    value = carTable.(fieldId);

            // Set the innerText of the XmlElement (field)
            // to the value from the table
            // Append the field as a child node to the record
         // Add the record as a child node to the root
    // Add the root to the XmlDocument
    // Create a new object of the XmlWriter class
    // in order to be able to write the xml to a file
    xmlWriter = XMLWriter::newFile(@"c:tempcars.xml");
    // Write the content of the XmlDocument to the
    // file as specified by the XmlWriter

The file that is created looks like the one in the following screenshot(only first part of the file is shown):

As you can see, this file is based on a standard XML format with tags and values only. You can, however, use tag attributes as well. To put the values from the table into tag attributes instead of their own tags, simply change the following code snippet in the example above

// Set the innerText of the XmlElement (field)
// to the value from the table

// Append the field as a child node to the record

With these lines:

// Add the attribute to the record
xmlRecord.setAttribute(, value);

The file that is created now looks like the one in the following screenshot: