How to capture a Trace log of any process in Dynamics AX 2012

Often times debugging a process is not enough to identify a bug or a query that is taking too long or the scenario only happens on a specific machine be it production or test and we need to get to the bottom of what is wrong that causes the issue. This calls for tracing the process and stepping through each cycle as it happened, thanks to Trace parser and the tracing cockpit provided in Dynamics AX 2012 we can capture every query executed and method called during that process. In the below video I show how to capture a trace log of any process.


Address and contact information table relationships to a party in #AX2012 & #Dyn365FO

Both address and contact information on a customer, vendor or any party record is stored at the party level. So while the parties Customer and Vendor are company specific the party record is cross company. If you create a customer against the same party in two companies and modify the address of Customer A in company X you will see the changes for Customer B in company Y. This is because when we are modifying a customers address or contact, it is actually modifying the party address and contact. You can test this out without getting into the development environment by creating a customer in one company with an address and contact, note down its party number that was created, then create a customer in another company and use the change party association option to assign the newly created customer the party number of the previously created customer. After this, change the address on any one of the customers and you will see the changes reflect on the other company customer as well. Now generally this is not the case as when you create a customer in a company a new party record gets created against it and within AX you always create a customer or vendor first and not a party itself.

Coming down to the technical’s in play for this. A party record is stored in the DirPartyTable and in order to query its locations(addresses/contact information) you can query the DirPartyLocation table which will give out  records that each represent an address and one record that represents all contact information records, to identify these there are NoYes enum fields such as IsPostalAddress. For example if there are 3 addresses on a customer and 5 contact information records, this table will show you 4 records. Each record contains a Location field that represents the RecId of  the LogicticsLocation table, this table contains links to the address and contact information records. Addresses are saved in LogisticsPostalAddress table and contact information is stored in LogisticsElectronicAddress table, each table has as relationship with the LogisticsLocation table as shown below.

Contains 4 records, 3 for addresses and one for contacts:

These records can be used to query the address in LogisticsPostalAddress table below, wrt to the following relationship:

Hopefully this gives you an idea of the crud operations of an address and contact information in AX. This applies to both AX 2012 and D365.

Change or Remove a dimension value on an Item through X++ in AX 2012

Using the below job you can update dimension values on an item.


static void UpdateDepartmentMISC_Items(Args _args)

InventTable inventTable;
DimensionAttributeValueSetStorage dimStorage;
DimensionAttribute dimAttDept, dimAttMisc;
DimensionAttributeValue dimAttributeValueDept, dimAttributeValueMisc;

DataAreaId company;
str misc, dept;
ItemId itemId;
int counter = 0;


info(strFmt('Start time: %1', time2StrHM(timeNow())));



inventTable = null;

dimStorage = null;

dimAttMisc = null;

dimAttDept = null;

dimAttributeValueDept = null;

dimAttributeValueMisc = null;

while select forUpdate inventTable

where inventTable.ItemId == itemId

&& inventTable.dataAreaId == curext()






dimStorage = DimensionAttributeValueSetStorage::find(inventTable.DefaultDimension);

dimAttDept = DimensionAttribute::findByName(#DepartmentDimensionToUpdate);

dimAttMisc = DimensionAttribute::findByName(#MISCDimensionToUpdate);

dimAttributeValueDept = DimensionAttributeValue::findByDimensionAttributeAndValue(dimAttDept, dept, true, true);


if (misc)


dimAttributeValueMisc = DimensionAttributeValue::findByDimensionAttributeAndValue(dimAttMisc, misc, true, true);





inventTable.DefaultDimension =;






error(strFmt("Error to update dimension for item %1", inventTable.itemid));





info(strFmt("Records updated: %1", Counter));

info(strFmt('End time; %1', time2StrHMS(timeNow())));


Resolving Visual studio tools 2013 installation error in AX 2012 R3 CU8

When trying to install visual studio tools the following error occurs “This installation package could not be opened. Verify that the package exists and that you can access it” This is mostly caused by VS tools folder missing inside the msi folder of your installation setup. If these folders are there then you might have a different issue. To resolve this for R3 builds follow the following blog by Microsoft support:

After this simply run your installer again and add the visual studio component, worked like a charm for me!


Time taken: 40mins

Transfer Demo data into AX 2012 R3

For transferring demo data into R3 versions of AX 2012 follow the below:


1 Get Demo data package and extract it into any feasible  location (Extraction will be large about 15-20GB)


Takes 20mins
2 Get Data transfer tool to transfer package extracted data in AX DB <<>>

3 Import MetaDataXMLGenerator.xpo into AX environment and run the job


Take 30mins

This will be found in the Data transfer tools folder you extracted above
4 Copy Metadata file generated as output of the above job to the [Lists] folder in the Data Transfer tool directory File is mostly generated at the following path





5 STOP AOS before moving to the next step  
6 Open command prompt as admin. Go to directory where Test import tool was extracted.

Run the following command


Takes hours (2-3 approx.)


DP.exe IMPORT “C:\Users\mohsin.khalid\Downloads\MicrosoftDynamicsAXR3CU8DemoData” MicrosoftDynamicsAx



FYI; In above command “MicrosoftDynamicsAx” is your ax db name




  Total time of activity 4 hours approx

How to Recall/Cancel a workflow through code in AX 2012

To recall a workflow through code you can use the cancelworkflow method in workflow class. It takes the correlationId and a comment as parameters and gets the job done for you. Example

workflow::cancelworkflow(CorrelationId, “Cancelling this workflow”)

Now you are probably thinking How do I find my workflows CorrelationId. You can do that by querying WorkflowTrackingStatusTable sorting it with time and instance number and joining it with SysWorkflowtable against the correlationId field and in the contextId you pass the RecId of your record for example PO RecId.

Fix for Error: Field ‘Company’ and ‘Lot ID’ must be filled in”

When editing a PO line for procurement category you receive Field ‘Company’ and ‘Lot ID’ must be filled in” error. This usually happens when you have brought in the PO line through some form of integration either AIF, excel plugin etc.

This error has also been seen on salesLine and there is a hotfix(KB 2756645) for when it happens on salesline.



There is no record in PurchLineForeignTradeCategory table related to PO line added.



Create a record against the PO line causing this error in the PurchLineFroeignTradeCategory table in your integration and you will see the error disappear.

Difference between Refresh(), Reread(), Research() and ExecuteQuery() in AX 2012

In X++ we have the below methods for fetching data after any changes are made, below is the short description of what they are and when to use each one.

Refresh() refreshes the user view with whats stored in the caches. This does not touch the DB.
Use this after any form change has been made through code.

ReRead() fetches only the current record from database and does not re read the complete datasource.
Use this when you need to update only the current record after modifying any value.

ReSearch() will execute the same query again and fetch the results from the database.
Use this if you need to get the current most data from database.

ExecuteQuery() will run the query again just like research does but it will also take any query changes into account.
Use this is you have modified the query on run-time and need the updated results according to the new query.