Recently one of my assignments, I have to explore and use Cross company queries to fetch data. Although cross company queries have performance overhead, for example, if my custom AIF service return result in 4 seconds , Cross company returns in 30 seconds.  I found multiple design pattern,  The fastest  cross company query are by setting allow cross property to set true in static AOT Query or by setting Adding In Query Object. Lets explore these patterns

Static AOT Query:

You can set Allow cross company true By properties of AOT Query .

 

Cross Company

 

X++ Query object:

One way to create query in dynamics Ax is Query object. You can add by following way.

 

Query query;

QueryRun queryRun;

QueryBuildRange queryBuildRange;

QueryBuildDataSource queryBuildDataSource;

query = new Query();

queryBuildDataSource = query.addDataSource(TableNum(CustTable));

query.allowCrossCompany(true);

//Executes query built so far

queryRun = new QueryRun(query);

queryRun.allowCrossCompany(true);

This is most fastest way to get cross company data.

 

While select Query:

 

There two ways for Get cross Company query and or Query inside the change company statement.

Cross company Keyword:

Add cross company query inside the while select statement to extract data all legal entities in Dynamics AX as  follow code.

Custtable _CustTable;

While select crosscompany * from _Custtable

{

Info (_Custtable.AccountNum + “   :  “ + int642str(_Custtable.DataAreaId);

}

 

If you want to restrict the query to fetch data from limited legal Entities you have to use a container as follow.

 

Container _ListOfLegalEntites ={ ‘mazang’,’Jubergi’,’Urdu Bazar’};

While select  crosscompany:_ListOfLegalEntites * from _Cust

{

Info(_Custtable.AccountNum + “  :  “ + _Custtable.DataAreaId);

}

 

Change Company Keyword:

 

One method is to use change company keyword. It is most time consuming method. To reduce its time, we have rest the table to null when Change Company happened. In Dynamics All legal entities name stored at  DataArea table we use this table to get the list of datarea and used inside the changeCompany  query on it as follow.

DataArea _DataArea;

Custtable _Custtable;

While select Id from _DataArea

changeCompany(_DataArea.Id)

{

_Custtable= null;

While select * from _Custtable

{

Info(_Custtable.AccountNum +”  :   “ + _Custtable.AreaId);

}

}

If you did not reset the table buffer , result will be too heavy, reason buffer contains old data as well. To reset or set null inside the change company statement and before query on buffer will be performance bust as well as design pattern.

 

 

 

{ Comments on this entry are closed }

Dynamics Ax 2012 : Exploring the Containers

by alirazazaidi on February 10, 2013

In Dynamics Ax there is structure known as containers. Here are some points for Containers

  • They are value based structure. So no class based object stored on it.
  • They are similar to linked list or array like structured.
  • Their size fixed at time of declaration. When you insert update or delete any value from container, a new container is created.
  • They always copied by value.
  • Containers are base 1 not like array based zero.

There is question arises why we use temporary tables when have containers . These containers which can stored almost very values data type value.  While there are lot of functions available for containers. Answer is that on temporary temple we can set indexes on fields and by this way we can fetch data much faster. Although data stored in container is sequentially but on insertion  a new copy is generated which is  performance over head. When data is increases in container, container starts to be heavy.  Similar when you passed temporary table to any method it passed by reference. But when we passed container to method, a new copy is generated and used in method. Container will used only when fewer values will be manipulated. In the case of larger set of data, we have to use temporary tables.

 

Declaration of containers.

container  firstContainer;

container  secondContainer = [3,"Ali","RAza"];

 

Read value from container.

The value from container can be read with conpeek function,  this method take two parameter, first one is container  and second parameter is for getting index. The conPeek function read value of any type so and read for any type.

 


_value  = conPeek(secondContainer,3);

 

 

Insert value:

 

There are two functions used for insert a value in container, conPoke and  conIns

 

ConIns

 


secondContainer=conIns(secondContainer,2,"Zaidi");

 

 

conPoke:

 

secondContainer=conpoke(secondContainer,2,”test");

 

There difference between conPoke and conIns is that conIns, insert a new value at location, and rest of value is shifted to one next Index. conPoke replace the value at insert location for example if

 

container  secondContainer = [3,"Ali","RAza"];
then conIns secondContainer=conIns(secondContainer,2,”Zaidi”);  will create new conainter like as

[3,”Zaidi”,”Ali”,”Raza”];

While conPok

secondContainer=conpoke(secondContainer,2,”test”);

will create a [3,”Zaidi”,”Ali”,”Raza”];

 

[3,"test","RAza"];

 

 

 

Removing the value from Container:

 

 

Condel function is used to remove the value from container.

secondContainer =conDel(secondContainer,2,1);

conNull function is used to clear all the value from container as

secondContainer=conNull() ;

 

Length of container is calculated as

int _lenght= conLen(secondContainer);

confind:

 

This method find the index the value which required to search, if value is not found zero will be return

 

_found =conFind(secondContainer,"RAza");

info(int2str(_found));

_found =conFind(secondContainer,"Abc");

 

 

 

Some important Global class functions for Container

 

 

Con2Str:

This method return container values as comma sparated string.

_value = con2Str(secondContainer);

 

Con2List:

This function converts the container into list.

List _myList=con2List(secondContainer);

 

 

Loop through container:

 

 

Usually we have to loop through the container.

 

 

_lenght = conLen(secondContainer);

for (counter =1; counter <=_lenght; count++)

{

_value=conPeek(secondContainer,counter);

info(_value);

}

 

 

 

 

{ Comments on this entry are closed }

Dynamics Ax 2012: Very simple report in dynamics ax 2012

by alirazazaidi on January 29, 2013

There two common and mostly used ways to develop reports in dynamics Ax 2012

  1. Query
  2. Report data Provider.

 

Here we have to create a very simple report using AOT query. For this purpose I have create a custom table Student with 4 fields as

  1. Rollnumber
  2. First Name
  3. Last Name
  4. Address

The sample data in custom table is as follow.

SampleData

 

 

Now we create a new Query in AOT which will be used in our Report to get data from AX to display on report.

In Query node of AoT create a new query Named it StudentsQuery.

Right click and on data source click on add new data source and on property window select or right Student table as follow.

StudentQueryDataSource

 

Click on Fields and from property window dynamics to yes.  Like as

Dynamic Fields

 

 

Now open a new  Project In Visual studio 2010. Select form Install templates  select Dynamics and then Report Model

Report Model

 

Now next step to add a new report in newly created Report Model project

I named it simple student report.

Now right click on Dataset and add a new dataset in report and Name it StudentDs and from property of data set you have set following property

DataSetProperty

 

 

Click on Query and form dialog box you have to search and select Query selected Query form Dynamics Ax. In this report we created the query with StuentsQuery. On selecting and press next a new dialog open you from here you can select fields required for report in this report we are just use 4 fields

DsStudent

 

 

 

After selecting field now create a new precision design.  Add new table and drop the field on column of table as follow. Press on review pane you find result like as

Report Result

 

 

 

{ Comments on this entry are closed }

Hi folks, Today i am searching for sample to write a blog entry for Ax deport development, i found very informative link at msdn which covers all portions of report development in Ax 2012.

 

http://msdn.microsoft.com/en-us/library/cc653472.aspx

 

 

Regards

Ali Raza Zaidi

{ Comments on this entry are closed }

It is common scenario in report development to use check boxes or radio button as parameter.  Any Boolean variable define at data contract class become check boxes at report dialog. But how we make radio button on report dialog. When we require radio button then it means we have more than two values and one value is required to select. For this purpose we have to create a new enum at AOT.   Let see we create a new base enum with Name Enum student.

BaseEnum

 

Right click on EnumStudent and open property window and set Style property as Radio button

EnumProperty

 

 

 

Now you have to create a new data contract class where we define parameter that will contain the selected value for enum.

 

 

 

[DataContractAttribute]

public class StudentDataContacts

{

EnumStudent enumStudent;

}

[ DataMemberAttribute('Student By'),SysOperationLabelAttribute('Student By')

]
public EnumStudent parmStudent(EnumStudent _EnumStudent =

enumStudent )

{

enumStudent = _EnumStudent;

return enumStudent;

}

When we deploy the report and run from menu Item, Report dialog will be appear like as follow screenshot.
Report Dialog

Now questions is that how we used this radio button parameter.

At report level, we can use this radio button parameter for grouping or such other operations. It return string value. For example I used here to just display what value of radio button selected in report Expression as

Expression

We can use this parameter inside the Process report method of Data Provider class as

public void processreport()
{
EnumStudent _EnumStudent;
str _StudentType;
StudentDataContact _DataContact;

_DataContact = this.parmDataContract();

_EnumStudent= _DataContact.parmStudent();

_StudentType=enum2str(_EnumStudent);

_TempStudentList.Firstname ="Ali";
_TempStudentList.LastName="Raza";
_TempStudentList.StudentType=_StudentType;
_TempStudentList.insert();

_TempStudentList.Firstname ="Raza";
_TempStudentList.LastName="Ali";

_TempStudentList.StudentType=_StudentType;
_TempStudentList.insert();

}

Hope this helps.

{ Comments on this entry are closed }

Dynamics Ax provide complex and interactive reports because they help gain valuable insights. One common report requirement is dynamic grouping which allows the users to choose which fields to group their data around.

In SSRS, dynamic grouping can be set up using the following steps.

Define the grouping parameters

To enable a dynamic grouping on a set of fields, create a parameter. List the fields you want to use for grouping and add labels. If you want grouping to be optional, also include null as a value (with a label like “None”).

  1. Click on Parameters, and then Add Parameter. In the Report Parameter Properties window, set the parameter properties.add-parameter

Select Available Values in the Report Parameter Properties window and add label and value pairs for all groups. Some times Report level parameter is not work, then you have to define this parameter at Data contract class. And used it as report level parameter.
set-available-values

Repeat these steps for each group of fields that you wish to enable dynamic grouping.
Create the report with grouping
Create a table report with the dynamic groups you set up. Groups like month, year and category are very common.

set-available-values

Set the group expression
Open the Group Properties window and Add the desired group expression.
Here is an sample expression where we perform some basic checks on our Month, Year and Category grouping and set the default display.
iif (Parameters!Group1.Value is Nothing,1,Fields(iif(Parameters!Group1.Value is Nothing, “Year”,Parameters!Group1.Value)).Value)
The outer iif checks for empty parameters and displays the entire group if this condition is met.
Otherwise, the second iif checks if the parameter value is Nothing which means none is selected from the drop-down and then it will return the value of the Year field without using it for any sorting or grouping.

group-properties1

Change the grouping display value (label) on basis of selected report parameter
The final step is to change the group label depending on the display value.
In this example, we are setting the Null value to display “Year” as the label in order to match the behaviour in the previous expression.
=Fields(if(Parameters!Group1.Value is Nothing “Year”, Parameters!Group1Value)).Value
group-display

{ Comments on this entry are closed }

This latest dynamics Ax version uses SQL Server Reporting Services (SSRS) as the primary platform for reporting. Developing in SSRS is much faster than X++ making custom reports easier to implement.

In addition to the use of SQL Server tools, there is an integration of the report development environment with Visual Studio 2010 making report development a lot more simple and straight-forward.

Most of the out-of-the-box reports are converted to SSRS platform.

There are two ways to design SSRS reports in AX.

  • Precision Design: created using SQL Report Designer when a precise layout is required.
  • Auto Design: automatically generated with the help of drag and drop action and selecting elements by using Model Editor.

AX 2012 also comes with the drillthrough reporting. This is a popular feature helps developers to link general reports to more specific ones and help the end users find insightful data.

{ Comments on this entry are closed }

Dynamics Ax 2012 provide the database level logging. You can track every change not only at table level but also at field of any table.

Dynamics Ax 2012 provide the functionality to log insert update and delete functionality on table as well as selected filed of a table. When tracking on any table in dynamics Ax, a new entry will be created in sysDatabaselog table.

Lets we enable logging on our custom “Student” table.

For this purpose you have to go “System Administrator” Module of Dynamics Ax 2012. Under Step tab you will find database node, there you find “Database log” Click on it. Like this.

dabase log

 

After that Database base logging Wizard will start

Wizard

 

Press Next. On next page select “Not Specified” node of tree. All custom table/ user table will be placed under “Not Specified” Node. Dynamics Ax Default tables are placed under their respected module name.

Node

 

 

Expend the not specified node.  And select the student table there.

 

Student

 

Here you can track not only table but also possible you can track one or more fields of specific table. In current example we enable tracking or logging on whole student table.

 

Studentselection

 

Now question is how we can see what will comes in in sysdatabaselog table on insert update or delete on table.  You can view from this link

 

Log view

 

 

Point to be noted, that all the tables where save per company enables, all log files will be appears in their legal entities. Data is stored in table globally or for all legal entities, you can find their log files under default legal Entity “Dat”.

Now we explore the database structure of SysDatabaselog table. This will help us to get the logged information in X++ code.

Followings are some important fields of SysDatabaseLog table.

  1. Table:  This filed contains the integer value for each table. A unique integer number attached to each table in dynamics Ax. This fileds tells us on which table operation is performed.
  2.     Creation Date: This contains the date and time on which entry in sysDatabaseLog is created.
  3. Data:  X++ container type this contains the data.
  4. LoggType: This described insert, update or delete operation is pefromed at the result current entry is done in sysDatabaselog. It is of enum type. DatabaseLogType::Insert

 

 

For example, if database logging is enabled on our student table, we can track all insert, update or deleted record form database log table. For example if we have to pull all inserted today records form sysDatabaselog we can do by following way.

 

SysDataBaseLog sysDataBaseLog;

utcDateTime CurrentDate;

container tableRecord;

container recordInstance;

str selectedField;

str fieldName;

str fieldValue;

int idx;

int tableID;

str  databaseLogSourceCompany;

CurrentDate=DateTimeUtil::newDateTime(today(),str2time(“00:00:00″));

tableID = tableName2id(‘Student’);

 

while SELECT sysDataBaseLog

WHERE sysDataBaseLog.table ==  tableID && sysDataBaseLog.createdDateTime > CurrentDate && sysDataBaseLog.LogType == DatabaseLogType::Insert

{

selectedField = “RollNumber”;

fieldName=”";

fieldValue = “”;

tableRecord = (sysDataBaseLog.Data);

 

for( idx = 1; idx <= conLen(tableRecord); idx++)

{

recordInstance =  conpeek(tableRecord, idx);

fieldName = conpeek(recordInstance, 1);

 

if(strLwr( fieldName ) == selectedField)

{

fieldValue +=” ” + conpeek(recordInstance, 2) + ” , “;

break;

}

 

}

 

}

{ Comments on this entry are closed }

I just start writing on Dynamics Ax reporting. To write on Dynamics Ax  starting point is what is Dynamics Ax reporting Model. On Searching I found that Dynamics Ax 2012 reporting Model is based on Model View Controller pattern.  It means reporting services can be replaced by any other report rendering application. Currently Reporting services are called from dynamics ax client,  Share point portal and job batch.

Reporting Services Architure

 

 

So what is Model view Controller Pattern is.

Model View controller is a pattern to de-couple the business logic from the user interface.

Model: Responsible for retrieving data, operation performed on data with respect to business logic, This part contains queries, Communication with data layer.

View : Responsible for User interface,  how to display data. Capable to show the data on different views.

Controller:  It controls or change the flow of data between Model and View. It send instruction to Model and send data to view, or responsible for change the view of data on view. Also responsible for update the Model for its data.

Typical Model view controller diagram is as follow.

MVC-Process (1)

In dynamics Ax 2012 Report model are
Model: SrsReportDataContractUIBuilder
View: SrsReportDataContract
Controller: SrsReportRunController

 

For more information please consult : MSDN: Reporting Programming Guide [AX 2012].

 

{ Comments on this entry are closed }

Dynamics Ax 2012 : Exploring the Query Service

by alirazazaidi on January 9, 2013

You can excess AOT query directly in your dot .net code. For this purpose I predefine AIF services comes with dynamics ax 2012. These services return data in dataset and paging mechanism you can handle large sum of data set. I my last example I create a student table with following fields.

FieldName dataType
Roll Number string
FistName string
LastName string
Address string
DateOfBirth date.

. To test the query services first we create a custom AOT services on Student table. For example I create a very simple query as following screen.
AOT Static Query

You can access query service with following url

http://[HostName]/DynamicsAx/Services/QueryService

After that I create a console application in visual studio to get dataset by calling Dynamics AOT static query in dot net code with the help of AIF Query services.
You can add services reference as
Adding Reference

I am creating Query reference with Namespace of QueryServiceTest.

QueryService Reference is added

Now in console application’s main method we call Query service and provide it AotQueryName and pageing object as follow. I am trying to fetch all the records form my custom Student table.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

namespace TestAIFQueryServices
{
class Program
{
static void Main(string[] args)
{

QueryServiceTest.QueryServiceClient _QueryClient = new QueryServiceTest.QueryServiceClient();
DataSet dataSet;
QueryServiceTest.Paging paging = null;

dataSet = _QueryClient.ExecuteStaticQuery("StudentQuery", ref paging);
foreach (DataRow dr in dataSet.Tables[0].Rows)
{

Console.WriteLine(dr["FirstName"].ToString() + " " + dr["FirstName"].ToString());

}
Console.ReadKey();

}
}
}

{ Comments on this entry are closed }