Skip to main content

Terminology - MS AX Technical

This method is invoked when a user inserts a new record or updates an existing one.
If there are several data sources on a form and they are joined then the sequence of methods invoked on "save" is something like this:

Validate write:
Determines whether data is valid and ready to be written.
Returns true if data is valid; otherwise, false.
This method is called from FormDataSource.write. If false is returned, the write operation is aborted and an error message is displayed.
This method will get to fire when we update a record.

Insert & doInsert:
Insert method is the normal method which get called when data insertion occur in table. Whereas doInnsert is the forceful insertion in to AX Tables I.e., it bypasses all the validation when inserting in to tables.
Ø  Calling DoInsert ensures that any Axapta X++ code written in insert method of the record is not executed.
Ø  Calling Insert always executes the Axapta X++ code written in the Insert method of the record.

This method get fired while creating new record to initialize a value, here I am assigning user id to the userID field.

public void initValue()
this.UserId = curuserid();

Each time the value of a field is changed the method modifiedField() is called. It is useful to initialize the values of other fields if the value of the current field is changed.

Example (2): Let’s now override modifiedField method for MyFirstTable and target is to set CurrencyCode to null when CustGroupId is modified.
public void modifiedField(fieldId _fieldId)
case fieldnum(MyFirstTable, custGroupId):
After adding this method, open table MyFirstTable using Table browser and try to modify custGroupId of an existing record, then you will notice that CurrencyCode is immediately set to blank.

ModifiedField() receives the field number of the active field as parameter. A switch statement is used to check which field is active. If none of the checked fields are active the super() call is executed instead.

A wonderful feature in Dynamics Ax is when a field value is modified, it is possible to re-call the value before the field was modified. This is made possible using orig() method. The field values can  retain their last committed value. The method orig() is used to get the stored value. Orig() will return an instance of the current table.
A single field value from orig() is retained by specifying the field. And When the record is committed orig() will be updated.
Syntax: print this.orig().custCurrencyCode;

Method validateField() is used for validation only and will return true or false. If the return value is false, the application user will be prevented to continue changing a field value.

Example (3): Let’s override validateField for MyFirstTable to verify the condition that CustName must be have >3 characters.
public boolean validateField(fieldId _fieldIdToCheck)
    boolean ret;
    ret = super(_fieldIdToCheck);
    if (ret)
    switch (_fieldIdToCheck)
    case fieldnum(MyFirstTable, custName):
        if (strlen(this.custName) <= 3)
        ret = checkFailed("Customer name must be longer than 3 characters.");
    return ret;
After adding this method, open table MyFirstTable using Table browser and press Ctrl+N, in the new record try to enter less than 3 characters for field custName, Ax will throw warning message stating “Customer name must be longer than 3 characters.” And you will be asked to enter value again. Thus we validate the data to be entered for a specific field.

Method validateWrite() will just check mandatory fields and is triggered when the record . Checks made by validateWrite() are the same as the super() call in validateField().So if your condition is not related to the value an application user enters in a specific field, you should put the validation in validateWrite().

When deleting a record the method validateDelete() is first executed. If true, the method delete() will be called.

Polymorphism is not the same as method overloading or method overriding. Polymorphism is only concerned with the application of specific implementations to an interface or a more generic base class. Method overloading refers to methods that have the same name but different signatures inside the same class. Method overriding is where a subclass replaces the implementation of one or more of its parent's methods. Neither method overloading nor method overriding are by themselves implementations of polymorphism.
Polymorphism in the context of object-oriented programming, is the ability of one type, A, to appear as and be used like another type, B. 
So, basically, any RunBaseBatch extension class (the ones you use to process stuff in AX) is an example of polymorphism in AX. Because they all call the methods of the base class as if they were their own.
And also method overloading is not supported in X++.

Super() is a call to the overriden method concerned in the super or parent class.
For the click event it does not serve any purpose since there is no change in functionallity if you remove it and you will not get any error.
For example:
if you create a class myCLASS1 and then inherit from it and override a method on it the call to super will execute the code from the inherited class.
If you remove super that code will not be executed and you may write different code for this method in the child class.

Display method:  
A display method is not a physical field in a table but rather a method of displaying information from another table or source. It appears like a "normal" field and it can be used in forms and reports.

A display method can be created on either a table (in which case it is available for all forms using that table), or on the datasource of a specific form (in which case it is available only on that form).
Display methods must be created using a specific signature, which varies depending on the location of the method.

Display methods on tables
When declared on a table, display methods must be preceded with the keyword display and expect no parameters. The following example is a standard display method from the SalesTable table.

display CustName customerName()
    return this.partyTable_CustAccount().Name;

Display methods on datasources
When declared on a form datasource, display methods must have one non-optional parameter. The following example is from the PurchEditLines form in standard Ax 2012. The parameter is a buffer of the same type as that of the datasource on which the method is declared. It is essential as, when viewing a grid on a form, the method must know for which row the return value is to be calculated.

//BP Deviation documented
display ImageRes backOrder(PurchParmLine _purchParmLine)
    if (-InventTrans::backOrderQtyIssue(_purchParmLine.ItemId, _purchParmLine.InventDimId) > 0)
        return #Imageinfo;

    return 0;

Edit method:

An edit method is not a physical field in a table but rather a method of entering and displaying information from another table or source. Like a display method it appears like a "normal" field and it can be used in forms and reports. For more information about display methods go to MSDN.
An edit method can be created on either a table (in which case it is available for all forms using that table), or on the datasource of a specific form (in which case it is available only on that form).
Edit methods must be created using a specific signature, which varies depending on the location of the method.
Edit methods on tables
When declared on a table, edit methods must be preceded with the keyword edit and expect exactly two parameters. The following example is a standard edit method from the SalesTable table.
Parameter _set indicates whether the edit method is being used to show (_set = false) or modify (_set = true) data. This is set automatically by the caller form.
Parameter _exchRate in the example below should be declared using the same type as the method return value, and contains the new value to be set when _set is true. Then _set is false then that value should be ignored by the method programmer.
Irrespective of the value of _set, the method must always return the current calculated value.
public edit SalesFixedExchRate editFixedExchRate(boolean _set, SalesFixedExchRate _exchRate)
    ExchangeRateHelper exchangeRateHelper = ExchangeRateHelper::newCurrency(Ledger::primaryLedger(CompanyInfo::findDataArea(curext()).RecId), this.CurrencyCode);

    if (_set)
        this.FixedExchRate = exchangeRateHelper.prepareExchangeRateForStorage(_exchRate);
        _exchRate = exchangeRateHelper.displayStoredExchangeRate(this.FixedExchRate);

    return _exchRate;

Edit methods on datasources:

On a form datasource, an additional parameter is required indicating against which record the method should operate. In the following example from standard Ax 2012 it is the _purchParmTable parameter. The order of the parameters is significant and must be followed exactly.

//BP Deviation documented
edit boolean  paymentIdValidated(boolean             set,
                                 PurchParmTable     _purchParmTable,
                                 NoYes              _validated)
    NoYes  validated;

    if (_purchParmTable.RecId)
        if (!paymentIdValidatedSet)
            paymentIdValidatedSet = new Set(typeName2Type(extendedtypestr(recId)));

        if (set)
            validated = _validated;
            if (_validated)
            validated =;
        validated = NoYes::No;

    return validated;

Table type: TempDB & InMemory:

In AX 2012 we have 2 different type of temporary tables. 
In Microsoft Dynamics AX, one type of temporary table is a TempDB table. We call them TempDB tables because their TableType property value is TempDB. This value comes from the TableType::TempDB enum value. The TableType property value can be set at AOT > Data Dictionary > Tables > MyTempDBTable > Properties > TableType.

All types of temporary tables are automatically dropped by the system when the table variable in X++ goes out of scope. A TempDB table is not dropped when you set its record buffer variable to null.
TempDB tables are a different type of temporary table than InMemory tables. 

InMemory - the type of temporary table which existed in the previous versions of Dynamics Ax.
     Such tables are held in memory and written to a local disk file once they
     grow beyond a certain point
TempDB - a new option in Ax 2012. They are "physical" temporary tables held in
     the SQL Server database.

The new TempDB tables operate in a similar manner to InMemory tables but support more features of standard physical tables:

Ø  More powerful joins with physical tables are possible, and are properly supported by the database.
Ø  Can be either per company or global.
Ø  Can be used from Enterprise Portal by using .NET Business Connector.
Ø  Can have foreign key columns.
Ø  Can have indexes columns.
Ø  Support for normal tts transactions.
Ø  Stores TempDB table in database.
Ø  Usable as a query: AOT > Query

To create a new instance link (populating data/copying reference) from one table instance
variable to the other with Temporary type tables:
For InMemory
    By using the 
setTmpData() method.
For TempDB
linkPhysicalTableInstance() method replaces the setTmpData() call.

For more details on TempDB capabilities, Limitations, How to use, Its lifetime please check here – 

Container and TempTable:
Microsoft Dynamics AX supports a special data type called a container. This data type can be used just as you would use a temporary table.

Data in containers are stored and retrieved sequentially, but a temporary table enables you to define indexes to speed up data retrieval. Containers provide slower data access if you are working with many records. However, if you are working with only a few records, use a container.

Another important difference between temporary tables and containers is how they are used in method calls. When you pass a temporary table into a method call, it is passed by reference. Containers are passed by value. When a variable is passed by reference, only a pointer to the object is passed into the method. When a variable is passed by value, a new copy of the variable is passed into the method. If the computer has a limited amount of memory, it might start swapping memory to disk, slowing down application execution. When you pass a variable into a method, a temporary table may provide better performance than a container.

This method basically refreshes the data displayed in the form controls with whatever is stored in the form cache for that particular datasource record. Calling refresh() method will NOT reread the record from the database. So if changes happened to the record in another process, these will not be shown after executing refresh().

Calling reread() will query the database and re-read the current record contents into the datasource form cache. This will not display the changes on the form until a redraw of the grid contents happens (for example, when you navigate away from the row or re-open the form).
You should not use it to refresh the form data if you have through code added or removed records. For this, you would use a different method described below.

Calling research() will rerun the existing form query against the database, therefore updating the list with new/removed records as well as updating all existing rows. This will honor any existing filters and sorting on the form that were set by the user.

The research method starting with AX 2009 accepts an optional Boolean argument _retainPosition. If you call research(true), the cursor position in the grid will be preserved after the data has been refreshed. This is an extremely useful addition, which solves most of the problems with cursor positioning (findRecord method is the alternative, but this method is very slow).

Calling executeQuery() will also rerun the query and update/add/delete the rows in the grid. The difference in behavior from research is described below.
ExecuteQuery should be used if you have modified the query in your code and need to refresh the form to display the data based on the updated query.

formDataSource.queryRun().query() vs. formDataSource.query()
An important thing to mention here is that the form has 2 instances of the query object - one is the original datasource query (stored in formDataSource.query()), and the other is the currently used query with any user filters applied (stored in formDataSource.queryRun().query()).
When the research method is called, a new instance of the queryRun is created, using theformDataSource.queryRun().query() as the basis. Therefore, if the user has set up some filters on the displayed data, those will be preserved.

Difference b/w Abstract class and Interfaces(C#)
An abstract class may contain complete or incomplete methods. Interfaces can contain only the signature of a method but no body. Thus an abstract class can implement methods but an interface cannot implement methods.

An abstract class can contain fields, constructors, or destructors and implement properties. An interface cannot contain fields, constructors, or destructors and it has only the property's signature but no implementation.

An abstract class cannot support multiple inheritance, but an interface can support multiple inheritance. Thus a class may inherit several interfaces but only one abstract class.

A class implementing an interface has to implement all the methods of the interface, but the same is not required in the case of an abstract Class.

Various access modifiers such as abstract, protected, internal, public, virtual, etc. are useful in abstract Classes but not in interfaces.

Abstract classes are faster than interfaces.

Thanks, Happy Daxing!! JJ