Caching Mechanism in AX:
Caching in simple terms, is a temporary storage area where frequently accessed data can be stored for rapid access. Once the data is stored in the cache, it can be used in the future by accessing the cached copy rather than re-fetching or recomputing the original data.In Ax, we have 2 caches.
1.Server Cache
2.Client Cache
Client Cache is used only when a select is executed on client-tier. If a record is not in client cache, it looks in server Cache, and if not, it costs a database fetch. Maximum records stored in client cache are 100 per table, per company, where as, in ServerCache, this limit is 2000.
To know whether a record is fetched from client cache, server cache or database, use wasCached() of the TableBuffer used in Select.
select * from salesTable where salesTable.salesId == '000006';
info(strfmt("%1",salesTable.wasCached()));
We have 2 types of caching mechanisms in Ax:
Set Based Cache – Caches a set of records.(EntireTable)Single-record Cache – Caches records based on Select Statement used.(NotInTTS, Found, FoundAndEmpty)
None: No data is cached or retrieved from the cache for this table.
This property value should be used for tables that are heavily updated or where it's unacceptable to read outdated data.
The Found and FoundAndEmpty caches cross transaction boundaries. The NotInTTS cache is newly created inside a transaction. This example, modified for the purposes of this topic, demonstrates how records are retrieved from the cache when the table's CacheLookup property is set to NotInTTS, and the PrimaryIndex property is set to a unique index on the AccountNum field.
Ex:
static void NotInTTSCache(Args _args) // X++, in AOT > Jobs.{
CustTable custTable;
;
// The query looks for a record in the cache.
// If the record does not exist in the cache,
// the query accesses the database.
select custTable
where custTable.AccountNum == '4000';
// The transaction starts.
ttsbegin;
// The cache is not used. The query accesses the database
// and a record is placed in the cache.
select custTable
where custTable.AccountNum == '4000';
// The query uses the database because
// the forupdate keyword is used.
select forupdate custTable
where custTable.AccountNum == '4000';
// The query uses the cache and not the database.
select custTable
where custTable.AccountNum == '4000';
// The query uses the cache because
// the forupdate keyword was used previously.
select forupdate custTable
where custTable.AccountNum == '4000';
// The transaction is committed.
ttscommit;
// The query will use the cache.
select custTable
where custTable.AccountNum == '4000';
}
If the table CacheLookup property was set to Found or FoundAndEmpty, the first select statement inside the transaction (after the TTSBegin statement) would retrieve the record from the cache.
In AX 2012, table caching is more advanced than in previous versions, including support for joins, unique indexes (as opposed to primary indexes only), cross company queries, etc. (under certain constraints as explained in the above links).
Links:
https://msdn.microsoft.com/EN-US/library/bb314693.aspx
https://community.dynamics.com/ax/b/axsupport/archive/2015/02/20/dynamics-ax-table-caching-basic-rules
http://tech.alirazazaidi.com/exploring-data-cache-in-dynamics-ax-2012/