Friday 11 March 2016

Performance Analyzer for Microsoft Dynamics

   Performance Analyzer for Microsoft Dynamics (Performance Analyzer) is the tool used by Microsoft Dynamics support, Premier Field Engineers, and product team members to diagnose performance issues with Dynamics products. 


Performance Analyzer for Microsoft Dynamics

   Performance Analyzer for Microsoft Dynamics (Performance Analyzer) is the tool used by Microsoft Dynamics support, Premier Field Engineers, and product team members to diagnose performance issues with Dynamics products. 


Dynamics AX Performance Optimization Guide

Yesterday I was in browsing to find some DAX performance oprimization tips as I am working on performance issues in AIF,AOS, SQL Traces and Batch Job optimizations. I found an interesting book.

http://community.dynamics.com/ax/b/axdilip/archive/2013/06/23/book-review-dynamics-ax-performance-optimization-guide

Dynamics AX Performance Optimization Guide

Yesterday I was in browsing to find some DAX performance oprimization tips as I am working on performance issues in AIF,AOS, SQL Traces and Batch Job optimizations. I found an interesting book.

http://community.dynamics.com/ax/b/axdilip/archive/2013/06/23/book-review-dynamics-ax-performance-optimization-guide

What are the diffrences between "index" & "index hint" in X++

I found a useful link which explaines about "index" and "index hint".

http://axaptafreak.blogspot.fr/2005/10/mystery-of-index-vs-index-hint.html

Create/Delete Customer using AIF Service Class in Dynamics AX without AIF Setup

The Application Integration Framework allows us to create/update/delete or read data. Now in AX2009 we have a facility of creating/deleting records using AIF Service classes. There is "NO ADDITIONAL AIF SETUP"(Like Enabling Endpoints etc.) required to execute the code via service class. The services can be used to read/write data in AX.


Create/Delete Customer using AIF Service Class in Dynamics AX without AIF Setup

The Application Integration Framework allows us to create/update/delete or read data. Now in AX2009 we have a facility of creating/deleting records using AIF Service classes. There is "NO ADDITIONAL AIF SETUP"(Like Enabling Endpoints etc.) required to execute the code via service class. The services can be used to read/write data in AX.


What are the diffrences between "index" & "index hint" in X++

I found a useful link which explaines about "index" and "index hint".

http://axaptafreak.blogspot.fr/2005/10/mystery-of-index-vs-index-hint.html

Remove the characters from string and convert to date to str in Axapta

strRem and date2str
Below job are to explain about how remove the characters from date and time in axapta

static void Job131(Args _args)
{
    str st;
    ;
    st = strRem(date2str(today(),213,2,0,2,0,4)+time2str(timenow(),                       TimeSeparator::Space,TimeFormat::Auto)," ");
    info(st);
}
Normally date and time will display like 09/25/2013 07:14:30 Am
By using date2str it will convert the date to str and again remove the character also .

Using File path on a form getting Error in Axapta

After a long time am coming  back to posting few new things here for AX Developer...

When we want to select the file path in form level. Normally what we will do create one EDT and extends with filepath (EDT), but that time when you are trying to select the path we will get error like stack-trace/Error message .Don’t worry there is no problem with your ax application. Simple we need to provide the method to the form like filepathLookUpTitle ().
Below method we need to add it into form level methods, i.e.

str filePathLookupTitle()
{
    return "Select document folder";
}

Using File path on a form getting Error in Axapta

After a long time am coming  back to posting few new things here for AX Developer...

When we want to select the file path in form level. Normally what we will do create one EDT and extends with filepath (EDT), but that time when you are trying to select the path we will get error like stack-trace/Error message .Don’t worry there is no problem with your ax application. Simple we need to provide the method to the form like filepathLookUpTitle ().
Below method we need to add it into form level methods, i.e.

str filePathLookupTitle()
{
    return "Select document folder";
}

Remove the characters from string and convert to date to str in Axapta

strRem and date2str
Below job are to explain about how remove the characters from date and time in axapta

static void Job131(Args _args)
{
    str st;
    ;
    st = strRem(date2str(today(),213,2,0,2,0,4)+time2str(timenow(),                       TimeSeparator::Space,TimeFormat::Auto)," ");
    info(st);
}
Normally date and time will display like 09/25/2013 07:14:30 Am
By using date2str it will convert the date to str and again remove the character also .

How to: Trace a Call to an AIF Web Service

How to trace a call from an external client to an X++ service exposed as a Web service in Microsoft Dynamics AX. When you call the Web service, the call goes to the Web service and is then passed to the AOS. You can use tracing to capture the parameters the client sends to the Web services as well as the parameters that are sent from the Web service to the AOS. 

https://msdn.microsoft.com/en-us/library/cc967372(v=ax.50).aspx

How to delete the file from particular location in Axapta

 WinApi::deleteFile(filepath);

strLfix & strRfix Function - Append zeros to the String - AX 2009

The following code used to append zeros to the string either left /Right.

static void Append(Args _args)
{
    int i = 1;
    str Append;
    str finalResult;
    ;

   Append= strlFix(int2str(i), 5, "0"); // Create a string, with a length of 5, ending with the value of ''i'' and padded with zeros
finalResult = strFmt("%1", Append);
info(finalResult);

}

strLfix & strRfix Function - Append zeros to the String - AX 2009

The following code used to append zeros to the string either left /Right.

static void Append(Args _args)
{
    int i = 1;
    str Append;
    str finalResult;
    ;

   Append= strlFix(int2str(i), 5, "0"); // Create a string, with a length of 5, ending with the value of ''i'' and padded with zeros
finalResult = strFmt("%1", Append);
info(finalResult);

}

How to delete the file from particular location in Axapta

 WinApi::deleteFile(filepath);

How to: Trace a Call to an AIF Web Service

How to trace a call from an external client to an X++ service exposed as a Web service in Microsoft Dynamics AX. When you call the Web service, the call goes to the Web service and is then passed to the AOS. You can use tracing to capture the parameters the client sends to the Web services as well as the parameters that are sent from the Web service to the AOS. 

https://msdn.microsoft.com/en-us/library/cc967372(v=ax.50).aspx

Troubleshooting BizTalk Web Services - AX 2009

how to identify and resolve common Web service issues.

https://msdn.microsoft.com/en-us/library/aa995583.aspx

Troubleshooting BizTalk Web Services - AX 2009

how to identify and resolve common Web service issues.

https://msdn.microsoft.com/en-us/library/aa995583.aspx

RPC errors when calling WinAPI method from a batch job.

I found a very good article about the errors and issues when we are calling WinAPI class from a Batch job.

https://blogs.msdn.microsoft.com/floditt/2009/01/29/rpc-error-1702-when-calling-a-winapi-method-from-a-batch-job/

RPC errors when calling WinAPI method from a batch job.

I found a very good article about the errors and issues when we are calling WinAPI class from a Batch job.

https://blogs.msdn.microsoft.com/floditt/2009/01/29/rpc-error-1702-when-calling-a-winapi-method-from-a-batch-job/

How to find USR Layer objects in entire AOT

I found some instersting content about how we can find the USR layer code in entire AOT.

http://theaxapta.blogspot.fr/2012/05/how-to-find-all-usr-layer-element-in.html

How to find USR Layer objects in entire AOT

I found some instersting content about how we can find the USR layer code in entire AOT.

http://theaxapta.blogspot.fr/2012/05/how-to-find-all-usr-layer-element-in.html

Finding out which tables were updated by an operation in AX

At times when troubleshooting Microsoft Dynamics AX you need to know which tables were updated by a particular operation, for example after performing a posting. This could be if you want to be sure that all the right tables are updated correctly after an upgrade, if you have unexpected results on one customer/vendor etc or if you have made an update the system and you want to be sure that everything is ok.


https://blogs.msdn.microsoft.com/axsupport/2013/09/27/finding-out-which-tables-were-updated-by-an-operation-in-ax/

Finding out which tables were updated by an operation in AX

At times when troubleshooting Microsoft Dynamics AX you need to know which tables were updated by a particular operation, for example after performing a posting. This could be if you want to be sure that all the right tables are updated correctly after an upgrade, if you have unexpected results on one customer/vendor etc or if you have made an update the system and you want to be sure that everything is ok.


https://blogs.msdn.microsoft.com/axsupport/2013/09/27/finding-out-which-tables-were-updated-by-an-operation-in-ax/

Setup & Config of AX 2012 R2 VM in VirtualBox

Here are the Links to Configure and instal Ax2012 VPC to Oracle Virtual BOX.

http://www.youtube.com/watch?v=klV6qh211EI

Setup & Config of AX 2012 R2 VM in VirtualBox

Here are the Links to Configure and instal Ax2012 VPC to Oracle Virtual BOX.

http://www.youtube.com/watch?v=klV6qh211EI

reRead( ) in AX 2009 - Best Advantage

To avoid most of the UpdateConflicts / DeadLock errors while update a record in a table, just use the "reRead( )" method of the table before making any changes to the selected record of the table.

Ex : 

;

ttsbegin;

select forUpdate tSalesLine where tSalesLine.SalesId = = 'SO-1234567';

tSalesLine.reRead( );

tSalesLine.Feild1 = XXXXX;
tSalesLine.Feild2 = XXXXX;

tSalesLine.update( );

ttscommit;

reRead( ) in AX 2009 - Best Advantage

To avoid most of the UpdateConflicts / DeadLock errors while update a record in a table, just use the "reRead( )" method of the table before making any changes to the selected record of the table.

Ex : 

;

ttsbegin;

select forUpdate tSalesLine where tSalesLine.SalesId = = 'SO-1234567';

tSalesLine.reRead( );

tSalesLine.Feild1 = XXXXX;
tSalesLine.Feild2 = XXXXX;

tSalesLine.update( );

ttscommit;

How to add Filter functionality to Display method in dynamics AXAPTA

This below code will work for filters to display method also.

Step 1:
Go to the form design right click on particular control properties Auto Declaration No to Yes.

Step 2:
Override the context() method on the display method .

public void context()
{
    int             selectedMenu;
    formrun         fr;
    Args            ag;
    Name            strtext;
    querybuilddataSource qb1;
    queryrun    qr;
    query       q;
    PopupMenu menu = new PopupMenu(element.hWnd());
    int a = menu.insertItem('Filter By Field');
    int b = menu.insertItem('Filter By Selection');
    int c = menu.insertItem('Remove Filter');
    ;
q   = ItemControl_ds.query();
qb1 = q.dataSourceTable(tablenum(ItemControl));
qb1 = qb1.addDataSource(TableNum(SalesTable));
qb1.addLink(FieldNum(ItemControl,PO),FieldNum(SalesTable,PurchOrderFormNum));

selectedMenu = menu.draw();
    switch (selectedMenu)
    {
    case -1: //Filter by field
            break;
    case a:
            ag = new args('SysformSearch');
            fr = new formrun(ag);
            fr.run();
            fr.wait();
//Reading User entered value for filter process
            strtext = fr.design().controlName('FindEdit').valueStr();
            if(strtext)
            {
//Creating a query for filter
                
                qb1.addRange(FieldNum(SalesTable,SearchName)).value(strtext);
                ItemControl_ds.query(Q);
                ItemControl_ds.executeQuery();
            }
            break;

    case b:                                      // Filter By Selection
           
            qb1.addRange(FieldNum(SalesTable,SearchName)).value(ProjName.valueStr());
            ItemControl_ds.query(Q);
            ItemControl_ds.executeQuery();
            break;

    case c :                                      // Remove Filter
            q   = new Query();
            qb1 = q.addDataSource(tablenum(ItemControl));
            qb1.clearLinks();
            qb1.clearRanges();
            ItemControl_ds.query(Q);
            ItemControl_ds.removeFilter();
            break;

    Default:
            break;
    }

}

How to pass control value in form to class in AXAPTA

Step :1

Write the method in Form level like :

public str method1()

{

         return control.Text();

}
Step 2:

Write this code in class level where we need to use the value

 if(formHasMethod(args.caller(), identifierStr(MethodName)))
    {
       strcustname =  args.caller().MethodName();
    

   }

Avoid warning message for "Empty compound statement" in AXAPTA

How to  avoid warning message like "Empty compound statement" in AXAPTA

As:
Simply call the below method inside your while loop or catch block to avoid best practice error

Call exceptionTextFallThrough(); in the block. It does nothing, it's there just to say that you're intentionally not doing anything there (and to satisfy compiler).

Avoid warning message for "Empty compound statement" in AXAPTA

How to  avoid warning message like "Empty compound statement" in AXAPTA

As:
Simply call the below method inside your while loop or catch block to avoid best practice error

Call exceptionTextFallThrough(); in the block. It does nothing, it's there just to say that you're intentionally not doing anything there (and to satisfy compiler).

How to pass control value in form to class in AXAPTA

Step :1

Write the method in Form level like :

public str method1()

{

         return control.Text();

}
Step 2:

Write this code in class level where we need to use the value

 if(formHasMethod(args.caller(), identifierStr(MethodName)))
    {
       strcustname =  args.caller().MethodName();
    

   }

How to add Filter functionality to Display method in dynamics AXAPTA

This below code will work for filters to display method also.

Step 1:
Go to the form design right click on particular control properties Auto Declaration No to Yes.

Step 2:
Override the context() method on the display method .

public void context()
{
    int             selectedMenu;
    formrun         fr;
    Args            ag;
    Name            strtext;
    querybuilddataSource qb1;
    queryrun    qr;
    query       q;
    PopupMenu menu = new PopupMenu(element.hWnd());
    int a = menu.insertItem('Filter By Field');
    int b = menu.insertItem('Filter By Selection');
    int c = menu.insertItem('Remove Filter');
    ;
q   = ItemControl_ds.query();
qb1 = q.dataSourceTable(tablenum(ItemControl));
qb1 = qb1.addDataSource(TableNum(SalesTable));
qb1.addLink(FieldNum(ItemControl,PO),FieldNum(SalesTable,PurchOrderFormNum));

selectedMenu = menu.draw();
    switch (selectedMenu)
    {
    case -1: //Filter by field
            break;
    case a:
            ag = new args('SysformSearch');
            fr = new formrun(ag);
            fr.run();
            fr.wait();
//Reading User entered value for filter process
            strtext = fr.design().controlName('FindEdit').valueStr();
            if(strtext)
            {
//Creating a query for filter
                
                qb1.addRange(FieldNum(SalesTable,SearchName)).value(strtext);
                ItemControl_ds.query(Q);
                ItemControl_ds.executeQuery();
            }
            break;

    case b:                                      // Filter By Selection
           
            qb1.addRange(FieldNum(SalesTable,SearchName)).value(ProjName.valueStr());
            ItemControl_ds.query(Q);
            ItemControl_ds.executeQuery();
            break;

    case c :                                      // Remove Filter
            q   = new Query();
            qb1 = q.addDataSource(tablenum(ItemControl));
            qb1.clearLinks();
            qb1.clearRanges();
            ItemControl_ds.query(Q);
            ItemControl_ds.removeFilter();
            break;

    Default:
            break;
    }

}

Caching inside AX

Dynamics AX Caching

Cache Location
Caches are used on both the client and the server. The Microsoft Dynamics AX runtime manages the cache by removing old records when new records are added to the cache.
Client Cache
A client-side cache can be used only by the client. The client cache is used when aselect is executed from the client tier. If no record is found in the client cache, the client then searches the server cache for the record. If the record isn't located in the server cache, it's retrieved from the database. The maximum number of records maintained in a client cache is 100 records per table for a given company.
Server Cache
A server-side cache can be used by any connection to the server. The server cache is used when a select is executed on the server tier. If no record is found in the cache, it's retrieved from the database. The maximum number of records maintained in a server cache is 2,000 records per table for a given company.
Record Caching
Microsoft Dynamics AX database record caching is a performance-enhancing feature that helps avoid database access when it's not strictly necessary. Retrieving database records from memory instead of the database significantly speeds up data access. Caching can reduce the performance penalty for repetitively accessing the same database records.
 Types of Caching

Caching is transparent to the application; however, it's important to know how caching works to optimize its performance in Microsoft Dynamics AX. Following are the types of caching:
  • Single-record
  • Set-based
Single-record caching has the following characteristics:
  • Defined at design time
  • Moves records to the cache based on the table's CacheLookupproperty and the type of SELECT statement that is used to retrieve the record

Set-based caching has the following characteristics:
  • Defined either at design time or in X++ code
  • Moves sets of records to the cache
  • Implemented either through the table's CacheLookup property or in code by using the RecordViewCache class
 Single-Record Caching
Record caching is enabled for a table when all the following statements are true:
  • The CacheLookup property on the table is enabled by setting it to one of the following values:
·         notInTTS
·         Found
·         FoundAndEmpty

  • The table's PrimaryIndex property is set to a unique index that exists on the table. The RecId index does not qualify as a caching index unless you set the table's PrimaryIndex property to this index.
  • The record buffer disableCache method has not been called with a parameter of true.
The fields in the table's unique index make up the caching key. A record is placed in the cache when the following criteria are met:
  • The table is cached by setting the CacheLookup property to notInTTS, Found, or FoundAndEmpty.
  • The SELECT statement that selects the records uses an equal operator (==) on the caching key. The fields in the WHERE clause of the SELECT statement match the fields in the index referenced by the table's PrimaryIndex property.
The table's CacheLookup property defines how and when records are cached as shown in the following table.
CacheLookup Property Value
Result
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.
NotInTTS
All successful caching key selects are cached.
When in a transaction (after ttsBegin), no caches made outside the transaction are used. When inside a transaction, the record is read once from database and subsequently from cache. The record is select-locked when read in a transaction, which ensures that the record cached is not updated while the transaction is active.
A typical example of the NotInTTS property is the CustTable in the Microsoft Dynamics AX standard application. It's acceptable to read outdated data from the cache outside a transaction, but when data is used for validation or creating references, it is ensured that the data is real-time.
Found
All successful caching key selects are cached. All caching key selects are returned from the cache if the record exists there. A selectforUpdate in a transaction forces reading from the database and replaces the record in the cache.
This is typically used for static (lookup) tables, such as Unit, where the record usually exists.
FoundAndEmpty
All selects on caching keys are cached, including selects that are not returning data.
All caching key selects are returned from caching if the record exists there, or the record is marked as nonexistent in the cache. A selectforUpdate in a transaction forces reading from the database and replaces the record in the cache.
An example of FoundAndEmpty record caching is in the Discount table in the Microsoft Dynamics AX standard application. By default, the Discount table has no records. By using a FoundAndEmpty cache on this table, the keys that are queried for but not found are stored in the cache. Subsequent queries for these same non-existent records can be answered from the cache without a round trip to the database.
EntireTable
Creates a set-based cache on the server. The entire table is cached as soon as at least one record is selected from the table.

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.
static void NotInTTSCache(Args _args)
{
    CustTable custTable;
    ;
// The query looks for records in the cache.
// If records don't exist, 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 records are 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 firstselect statement inside the transaction (after the TTSBegin statement) would retrieve the record from the cache.









Set-Based Caching
In Microsoft Dynamics AX, groups of records can be cached all at once with set-based caching. Set-based caching can be implemented in two ways:
  • At design time, by setting the table's CacheLookup property toEntireTable.
  • In code, by using the RecordViewCache class.

EntireTable Cache
*         
When you set a table's CacheLookup property to EntireTable, all the records in the table are placed in the cache after the first select. This type of caching follows the rules of single record caching in which the SELECT statement WHERE clause fields must match those of the unique index defined in the table's PrimaryIndex property.
The EntireTable cache is located on the server and is shared by all connections to the Application Object Server (AOS). If a select is made on the client tier to a table that is EntireTable cached, it first looks in its own cache and then searches the server-side EntireTable cache. An EntireTable cache is created for each table for a given company. If you have two selects on the same table for different companies the entire table is cached twice.
Joins that include an EntireTable cached table are only performed against the cached copy when all tables participating in the join are EntireTable cached. Otherwise a database join is performed.
Important Note:
Avoid using EntireTable caches for large tables because once the cache size reaches 128 KB the cache is moved from memory to disk. A disk search is much slower than an in-memory search.
Flushing the Cache

An EntireTable cache is flushed whenever an insert, update, or delete is made to the table. At the same time, the AOS notifies other AOSs that their caches of the same table must be flushed. After the cache is flushed, a subsequent select on the table causes the entire table to be cached again. Therefore, avoid caching any table that's frequently updated. Regardless of when updates are made, EntireTable caches are flushed every 24 hours by the AOS.
RecordViewCache Cache
*         
Set-based caching is implemented in code by using the RecordViewCache class. You must first create a record buffer using the nofetch statement and then pass the record buffer to the RecordViewCache class when it's instantiated.
The cache is created on the server and is only accessible by the process that creates the cache object. Once the cache is instantiated, all select statements are issued against the cache, as shown in the following
static void RecordViewCache(Args _args)
{
    CustTrans       custTrans;
    RecordViewCache recordViewCache;
    ;
    // Define records to cache.
    select nofetch custTrans
       where custTrans.AccountNum == '4000';

    // Cache the records.
    recordViewCache = new RecordViewCache(custTrans);

    // Use cache.
    select firstonly custTrans
        where custTrans.AccountNum == '4000' &&
              custTrans.CurrencyCode == 'USD';
}

Due to concurrency issues, the forUpdate keyword on the instantiating X++SELECT statement should only be used when all of the records in the result set will be updated. Otherwise it's a better strategy to use select forUpdate only for the records that are to be updated.
The RecordViewCache class is used in a select when the select is from a table that's cached, the select statement doesn't participate in a join and the selectWHERE clause matches the WHERE clause with which the RecordViewCache was instantiated.
The cache created by the RecordViewCache class stores records in a linked list. Therefore Microsoft Dynamics AX searches the cache sequentially for records that match the search criteria. If the SELECT statement contains an ORDER BY clause, a temporary index is placed on the cache and the runtime uses the index when searching records.