Showing posts with label AX 2012. Show all posts
Showing posts with label AX 2012. Show all posts

Wednesday, August 18, 2021

Move new code changes after D365 FinOps upgrade project start

If you are upgrading from AX 2012/AX 2009 to D365 FinOps, you need to do the code freeze before starting the code upgrade step. But we can’t avoid the bugs and high priority changes, in these scenarios, we do the code changes and later we need to move those changes to D365 FinOps. Unfortunately, we don’t have any tool to import XPO file in D365 FinOps.


How the upgrade process works and why we need code freeze?

The upgrade team take the model store and business database backup and import the model store on LCS and LCS upgrade tool converts the AX 2012 model store to D365 FinOps codebase and some code conflict issue will appear based on our customization, so the upgrade team need to fix those issues. So, our new AX 2012 system code changes are detached with D365 FinOps codebase, in other words, there is no link between our AX 2012 system and D365 FinOps. It is very high level, refer here for more information.

Once the upgrade process is done and got the development environment, we need to move our code changes.


Consider the followings

1. Which bugs we fixed

2. Which change request we worked

3. What are objects are modified/created for the specific bug/change request

4. What change we done on the objects for the specific bug/change request


It is very complicated process, if you don’t have project management system. In this case, we need to capture every change on Excel or somewhere and need to keep xpo before change and after change.


It is very simple, if you are already using DevOps for both project management and source control. Before upgrade start, move current sprint’s pending changes to production and make a note that from which sprint we need to move our new changes. That’s it.


Whenever we do the code check in, we need to select the specific work item, so we can easily track what are the changesets are involved for the specific DevOps work item.


If you did lot of customization after upgrade,

1. We can export model store and import on LCS and follow the same upgrade process and move your changes, but it is very complicated process and we need to invest lot of time.


2. The second option is manual code move, 

First you can move data dictionary related changes to D365 FinOps, so the upgrade team no need to wait for you to do the latest production data upgrade. Slowly we can move our classes or reports related changes.

We can’t easily compare the report design related changes between two versions. So, better open the report on VS in AX 2012 server and copy the rdc file to D365 FinOps machine and open in VS, restore the dataset and copy paste the entire design elements.


For more information related to AX 2012 version control, please refer here


Sunday, August 15, 2021

Who is running the SSRS reports

In sometimes, we need to see who is using the specific SSRS report or need to understand which report is used frequently or what kind of reports are used for specific user.

The SSRS report history is stored in ReportServer database. The view name is ExecutionLog3.

We can use the following query to fetch the data.


USE ReportServer

SELECT  * FROM ExecutionLog3

ORDER BY TimeStart DESC


We can get the user details on Username column. The username column works only for AX 2012. The username column is not working for D365, because in AX 2012 we can give report permission for specific user, in D365 if user having permission for report then the user can run the report.


Monday, January 18, 2021

The ESS page changes are rolling back automatically

If we edit the page on ESS (Site Actions -> Edit Page) directly, we need to import the page definition on AOT otherwise, our changes will be rolled back when we restart the AOS or after full compilation.

Find your edited page's web menu, right click and click "Import page". It will update the page definition on your AOT.

You can find the page definition name (Web-> Web files -> Page definitions) on the web menu's property.

Friday, May 10, 2019

Use import and export wizard to import records from backup database


Accidently two table records are deleted. So, we planned to restore the records from the backup database. We can export the records in CSV file and import the records by using X++. But, we need the records with same RecId.

In SQL, we have import and export tool to copy the records from source to destination tables. Before import the records, we deleted all records from the source tables to avoid duplicate record creation.

So, we have imported the records from the old database backup within 2 minutes. It is not recommended to insert the records directly in the AX database. But we don’t have any other option to fix this issue ASAP.

Please refer into the below link to understand that how to use import and export tool.

Restore AX database backup in same instance with different name


We have a daily AX production database backup up plan. One day we faced a problem in the production. Some of the records are deleted. So, we planned to analyse with latest backup.

We got the below error message, when we try to restore the recent backup file with different database name.

Error message:

“The backup set holds a backup of a database other than the existing 'Test3' database.
RESTORE DATABASE is terminating abnormally. (Microsoft SQL Server, Error: 3154)”

Solution:


Steps:

  1. Move the production database into offline mode. The database name is MicrosoftDynamicsAX.
  2. Copy and paste the mdf and ldf files in different location
  3. Move the production database into online mode
  4. Delete the MicrosoftDynamicsAX database
  5. Restore the recent database backup file with different database name (MicrosoftDynamicsAX_Backup), mention the different filename for mdf and ldf files and check the “Overwrite the existing database” option as per the post https://blog.sqlauthority.com/2013/11/23/sql-server-fix-error-3154-the-backup-set-holds-a-backup-of-a-database-other-than-the-existing-database-ssms/
  6. Once restored successfully, we can attach the production database MicrosoftDynamicsAX
  7. This is only for the initial time, after that we can restore the database into MicrosoftDynamicsAX_Backup database anytime.

Monday, May 6, 2019

Cannot create a record in user information (sysuserinfo)

We faced some issue on the development server. It will take some days to resolve the issue. So, we planned to use UAT server as development server for temporarily. The AX version is AX 2012 R3 CU11. We don’t have Visual Studio 2013 in the test server. So I downloaded and installed the Visual Studio 2013 professional edition and installed Visual Studio development tools.

I got the error message “cannot create a record in user information (sysuserinfo)” after the Visual Studio development tools installation. I googled and found the discussion on this URL https://community.dynamics.com/ax/f/33/t/246540

As per the community, post I tried to delete the AUC file and KTI files. It worked fine.

What is AUC file?

The AUC stands for Application Unicode Cache. It is a cache file. Cache file is mostly used to improve the application performance. But if the cache object is older than our server objects, then we may face some issues like the code work fine in server/developer machine but, other user will get error. The xpo move might be one of the reasons for this issue.

In my case, I just installed the Visual Studio development tools, not done anything in the model store. So, I believe AUC cache files are not only supporting to coding objects, some of the cache is supporting to run the AX application.

Friday, February 17, 2017

Table synchronization issue – Cannot select a record in table

We may get this below error message sometimes when we remove the existing field.

My case I have removed the field “TestField”. After I removed the field, I got the below error message when I open the form.

That form using my modified table as form data source. After I removed the field the synchronization is not happened correctly. So, I right clicked the modified table and clicked synchronize. It worked.

If the above solution is not working, then you may need to do the full DB synchronization.

Error message:
Cannot select a record in Hari_TestTable (Hari_TestTable).
The SQL database has issued an error.
SQL error description: [Microsoft][SQL Server Native Client 10.0][SQL Server]Invalid column name 'TESTFIELD'.
SQL statement: SELECT T1.MODIFIEDDATETIME,T1.MODIFIEDBY,T1.CREATEDDATETIME,T1.CREATEDBY,T1.RECVERSION,T1.PARTITION,T1.RECID FROM HARI_TESTTABLE T1 WHERE (((PARTITION=?) AND (DATAAREAID

Unretrieved value in form field

Unretrieved value in form field

When we add new fields in the table, it will synchronize with database and new fields will be created in SQL table. Sometimes, In the form level we couldn’t see newly added field value, instead it will show the value "Unretrieved”.

If we check table browser, it will show the correct value. To refresh the form field value, we need to select the field and press the Ctrl+F5.

To resolve this issue, we can do the following steps.

  1. Tools -> Caches -> Refresh elements
  2. If the first point is not resolve this issue, restart the AOS. Restarting AOS will resolve this issue. My case first point not worked.





Wednesday, February 15, 2017

Disk space - error message "Error in file - while writing in record"

Windows error “Error in file” message when we open AX rich client application

Sometimes, we will get this below error message. It is coming because of AX AOS server’s disk space issue. My case it is showing C:\ drive. To resolve this issue, we need to clear disk space.

Error message:
---------------------------
Warning
---------------------------
Error in file: C:\Users\Hari~1\AppData\Local\Temp\$tmp00030007.$$$ while writing in record = 5FE00
Windows error:  =
Error code: 112 = Unknown error

Try again?

---------------------------
Yes   No
---------------------------

Wednesday, September 14, 2016

Take a backup of particular tables data in SQL

Some cases we need to delete the data from the table. We can delete the record from AX or directly from SQL database by using delete SQL. Before delete the record, we are checking more than 3 times. Because, it is all business data.

If we have deleted the wrong data, we can’t revert back if you weren’t take the backup before delete. So backup process is necessary before do the delete operation. Database backup and restore will take more time. Instead of taking a whole database backup we can take a particular table data backup before do the delete operation for a particular table.

We can take the table data backup through SQL Server Management Studio. SSMS having an option for table data backup.

Here, I will share the screenshots step by step.





Select the table(s) that you want to take a backup

Mention the backup SQL file path.

Select the data only option




To restore the data, you can open the output SQL file in SQL Server Management Studio and connect the server and execute the SQL file script.

Thank you.

Saturday, August 27, 2016

Cross-reference tool

Introduction to cross-reference tool:

Cross-reference tool is one of the Microsoft Dynamics AX IDE. It is used to find the relationships between the objects. If you want to know what are the objects are used in a particular class or what are the objects are using a particular class, you can use cross-reference tool.
For example:
I have one output menu item, but I don’t know where this menu item is used. I need to find the menus for the particular menu item. So, the solution is that I have to look all module menus manually. Instead of finding manually, we can use cross-reference tool.

To find the menus for the particular menu item:

Right click on the menu item > Add-Ins > Cross-reference - > used by
It will give you the list of objects that are using this menu item. In the result window, you can find the menus object also.

If you click using option, it will give you the list of objects used in the selected menu item. It may give you the form of the selected output menu item.


Cross-reference results are coming from the following tables.

  1. XREFNAMES
  2. XREFDIALOGUPDATE
  3. XREFREFERENCES
  4. XREFPATHS
  5. XREFTABLERELATION

To create/update the cross-reference

By default, cross-reference don’t have data. To create the cross-references you need to configure manually by navigating to, in the development workspace, open the Tools menu, and then click Cross-reference > Periodic > Update. The Update cross-reference window appears. Select update all and click OK button. It will create a batch job and start running the batch job.

After completed the cross-reference update, if you create a new object in AOT, that created object reference won’t be updated automatically in cross-reference. We need to do manually by right click on the object > Add-Ins > Cross-reference > Update. You need to do the same job again after you modified the object.

Automatic cross-reference update

Instead of doing this manually, we can set automatic process when the compiler compile the objects. To set this option, development workspace > Tools > Option > Development > click compiler button > check cross-reference checkbox and click OK button.

It will affect your performance, because it will run whenever compiler compiles the objects. If you don’t want immediate update, you can go for the scheduling process for every week or end of the day or etc. Refer into this link for cross-reference scheduling https://msdn.microsoft.com/en-us/library/cc566587.aspx.

For more information, please refer https://msdn.microsoft.com/EN-US/library/aa626961.aspx

Sunday, August 9, 2015

Index

Index:

Indexes are used to improve the database search and retrieve functionality. We can add one or more fields in the indexes. Indexes are managed automatically by the DBMS when we do the operation insert, update and delete. We don’t want to create the index if the table mostly used for insert the values. Index is right choice for tables that mostly using for search functionality. We can’t create index for the datatypes memo and container fields. In AX 2012, all tables having default index for the fields recid and dataareaid.

Two types of indexes are in AX 2012.
  1. Unique
  2. Non unique

Unique:

We can unique index by setting the property AllowDuplicates to Yes. Once we created the unique index for the fields, we can’t insert duplicate value, the system will handle automatically and throw error message when we insert the duplicate values. We can select the unique index as table primary index.

Non unique:

It allows duplicate values.

We can enable and disable the index by setting the index property Enabled. DBMS will handle index once you re-enable the index. We can also delete the index.

We can use the index in the select statement to improve the fetching speed. For example

while select AccountNum, Name from custTable index AccountIdx { ……. }

Monday, May 18, 2015

Ternary Operator (?)

Introduction:

Ternary operator is a conditional statement. It is related to the If condition, but it assigns value to the variable. Based on the scenario, we can use ternary operator instead of If condition.

Syntax:

expression1 ? expression2 : expression3

Expression1 must be a Boolean expression. Expression1 may be a condition for example:

salaryDeduction = calculatedDeduction > 500 ? calculatedDeduction - 500 : 0;

expression2 and expression3 must be a same data type otherwise, it will be consider as error. You may get warning/error message like “Operand types are not compatible with the operator”.

As per the above code if the calculatedDeduction is more than 500 then expression2 result value will be assigned to the variable salaryDeduction else 0 will be assigned to the variable salaryDeduction. It is also possible to use ternary statement nested inside another ternary statement. Last time, I tried this ternary operator in the update_recordset, but not supported.

Replace If condition:

Based on the scenario, we can use ternary operator instead of if condition.

Saturday, May 16, 2015

Array

Introduction:

Array is a collection of same data type variables. We can access the each element in the array by using index. The index is start with 1. Sometimes, we have to deal with same data type value collections like name of the persons. For this scenario, we can use array data type.
Array data type is one of the composite data type in AX 2012. We can’t use Array data type for store the class objects. But, we can use Array collection class instead of Array data type.
AX 2012 supports only single dimension array not multi dimension array.

Array example:

static void Hari_TestJob(Args _args)
{
    str empName[10];       // Fixed-length array with 10 integers
    empName[1] = 'Hari'; //Assign value to the 1st element in the array
    print empName[1];     //Accessing the 1st element in the array
    pause;
}

Types of array

Three types of arrays are in AX.
  1. Fixed length
  2. Dynamic length
  3. Partly on disk


Fixed length:

Declare the length of the array in the variable declaration section. For example:
    str empName[10];
As per the above declaration code, we can hold only 10 values in this array.

Dynamic length:

Declare the array without mention the length. For example:
    str empName[];
Array length is the unlimited here. Array length is calculated based on the maximum element index used.

Partly on disk:

Partly on disk is some elements occupied in memory and others are occupied on disk. We can use fixed length array and dynamic length array in the partly on disk type. We can use this type for performance optimization when deal with lot of data. For example:
    //Fixed length array in the partly on disk array type,
    //here 20 items in the memory and 100 items in the disk.
    str empName[100, 20];
    //Dynamic length array in the partly on disk array type,
    //here 20 items in the memory and other items in the disk.
    str empName[, 20];

Reset the array values:

We can reset all array element value by assign any value to the 0 element of the array. For example:
static void Hari_TestJob(Args _args)
{
    str empName[10];
    empName[1] = 'Hari';
    empName[0] = '';         // Reset the array values
    print empName[1];
    pause;
}

Get the array length:

We can get the length of the array by using the dimOf function.


Tuesday, April 7, 2015

Useful functions for container

conLen:

conLen function is used to get the container length.

conPeek:

conPeek is used to get the container content by index. Note: index starts by 1.

conIns:

conIns function is used to insert one or more elements into a container. For example:
static void Hari_Test_ConIns(Args _args)
{
    container   c;
    int         i;
    c = [3, 'third'];
    c = conIns(c, 1, 1, 'first', 2, 'second');
   
    for(i = 1; i <= conLen(c); i++)
    {
        info(strFmt('%1', conPeek(c, i)));
    }
}

Result:
1
first
2
second
3
third

Note: += is faster than conIns function. We can use conIns when you want to insert the element in the particular index.

conDel:

conDel function is used to delete the one or more elements from the container. For example:
static void Hari_ConDel(Args _args)
{
    container   c;
    int         i;
    c = [3, 'third'];
    c = conIns(c, 1, 1, 'first', 2, 'second');
    c = conDel(c, 5, 2);
    for(i = 1; i <= conLen(c); i++)
    {
        info(strFmt('%1', conPeek(c, i)));
    }
}

Result:
1
first
2
second

conFind:

conFind function is used to find the sequence elements in the container. For example:
static void Hari_ConFind(Args _args)
{
    container c = ["item1", "item2", "item3"];
    int i, j, k, l;
    ;

    i = conFind(c, "item2");
    j = conFind(c, "item1", "item2");
    k = conFind(c, "item1", "item3");
    l = conFind(c, "item4");
   
    print "Position of 'item2' in container is " + int2Str(i);
    print "Position of 'item1 item2' in container is " + int2Str(j);
    print "Position of 'item1 item3' in container is " + int2Str(k);
    print "Position of 'item4' in container is " + int2Str(l);
    pause;
}

Result:
Position of 'item2' in container is 2
Position of 'item1 item2' in container is 1
Position of 'item1 item3' in container is 0
Position of 'item4' in container is 0

conNull:

conNull function is used to empty or dispose the contents of the container.

conPoke:

conPoke function is used to replace the contents of the container from the particular index. For example:
static void Hari_TestJob(Args _args)
{
    container c1 = ["item1", "item2", "item3"];
    container c2;
    int i;

    void conPrint(container c)
    {
        for (i = 1 ; i <= conLen(c) ; i++)
        {
            print conPeek(c, i);
        }
    }
    ;
    conPrint(c1);
    c2 = conPoke(c1, 2, "PokedItem", "Test");
    print "";
    conPrint(c2);
    pause;
}

Result:
item1
item2
item3

item1
PokedItem

Test

Container Data Type in AX 2012

Introduction

Container is a one of the data type in ax. We can hold more primitive data type values in a single container. Container index starts by 1 not 0. For example:

container   c = ['Test', 27];
info(strFmt('%1 - %2', conPeek(c, 1), conPeek(c, 2)));

Result: Test – 27

Table Field Type:

Container is one of the table field data type. So, we can store the container directly in to the database table field. In SQL, container table field data type is treated as varbinary datatype field.

Store container in another container:

We can also store one container in another container. For example:

int         i;
container   c = ['Test', 27], d = ['Second'];   
c += d;
   
for(i = 1; i <= conLen(c); i++)
{
    info(strFmt('%1', conPeek(c, i)));
}

Result:
Test
27
Second

Value based:

It is a value based structure. We can’t store any class objects in this container. It is not a reference based data type. If you assign one container in another container, the container will be copied not linked by reference. For example:

int         i;
container   c = ['First'], d;   
c += d;
d += ['Second'];
for(i = 1; i <= conLen(c); i++)
{
    info(strFmt('%1', conPeek(c, i)));
}

Result:
First

When we use container

As per the above code, we add d container in c and adding “Second” string value in the d container after adding. But “Second” value is not added in the c container. So, if you pass container as argument to the method, it creates new container. So, performance will be slow.
If you want to handle different data types, container is the good choice. But, if you add repeated value like list in the container, it is not a good choice, because it will affect performance.

Containers are immutable

Immutable means once the variable is declaration, we can’t change the size. Here container is an immutable object. When we add, delete and update the container, new container will create.

The following statements all create a new container.

myContainer = [1]; // new container created for myContainer
myContainer += [2]; // new new container created for myContainer
myContainer4 = myContainer5; // new container created for myContainer4

Insert performance:


+= is faster than conIns function. We can use conIns when you want to insert the element in the particular index.

Sunday, April 5, 2015

Primitive data types in AX 2012

1. Anytype Data Type:

Anytype is a placeholder for any data types (integer, real, string, container, class, etc.).
Please refer this link for more information.

2. Booleans

We can use Boolean for true or false values.

3. Dates

Dates data type is used to handle date value (date, month, year).

Assign value:
date d1 = 31\3\2015;

We can add days and subtract date easily. For example:
date d1 = 31\3\2015;
d1 = d1 + 3; //Add two day, result: Apr 3, 2015
d1 = d1 - 1; //Subtract one day, Result Apr 2, 2015

Date range is Jan 1, 1900 to Dec 31, 2154

4. Enums

Enum is an abbreviation of enumerated text. It contains list of literals. Enum literals represented as integer values. First Enum literal value is 0, next literal value is 1 and so on. We can use maximum 251 literals in single Enum.

We can create Enum in the AOT -> Base Enums.  We can declare this Enum in X++ like other data types (ex: Integer)

Declaration:
NoYes    isCompleted;

Assign value:
isCompleted = NoYes::Yes;

If you assign this Enum data type EDT in the combo box, the Enum literals are coming as combo box options.

Enums as Radio button
If you drag the form data source enum field in the design, the combo box control will be added (combo box is default control for enums). If you want radio button (radiobutton) control instead of combo box, add the radio button control by right click on design node and go to New Control -> RadioButton. Set the data source and data field property of the radio button.

If you want to set Enums in the un bound radio button control, select the Enum Type or use ExtendedDataType properties.

5. GUIDS

GUID is a Globally Unique Identifier. It is a unique no across all computers and networks. The unique identifier is generated by Microsoft algorithm. We can use this data type if we need globally unique no.

Hint: To check the GUID empty value, we can use the nullValueBaseType Global class method.
Example:
if(this.PurchReqLineRefId == nullValueBaseType(Types::Guid))

6. Integers

It is a number without decimal point.
Two integer types are there:
int (32 bit)
int64 (64 bit)
int range is - 2,147,483,648 to 2,147,483,647
int64 range is - 9,223,372,036,854,775,808 to 9,223,372,036,854,775,807

Declaration:
int a = 27;

7. Reals

Real data type is used to hold decimal numbers.

Declaration:
real   r1 = 10.03;

8. Strings

It is used for strings (number of characters). Range is unlimited.
We can set the length in the StringSize property of the EDT or table field. In X++, we can set maximum length in the declaration section. For example:
str 60 testStr;
As per the above declaration code, we can assign only 60 characters.

9. TimeOfDay

TimeOfDay datatype variable is used to hold time of the day. It represents integer value. Its range is 0 to 86400 (86400 means 23:59:59).

TimeOfDay   t1 = 28800;
info(strFmt('%1', time2str(t1, TimeSeparator::Colon, TimeFormat::AMPM)));

Result: 08:00:00 am

time2str function is used to display the time in the specify format.

10. UtcDateTime

UtcDateTime variable is used to hold date and time value.

Assign value:
utcdatetime myUtc2 = 1988-07-20T13:34:45;

Thursday, March 26, 2015

Variable declaration

Variable declaration

Variables must be declared first in the method. We can’t declare the variable inside the X++ statements. In other languages like .net, VB we can declare wherever you want. In AX 2009 we should use semicolon (;) to separate the declaration part and X++ statements like the below code.

AX 2009 variable declaration

int a;
;
a = 5;

But, in ax 2012 semicolon is not necessary (optional). We can assign values in the declaration part.
int a =5;

Variable name

In X++, variable names are not case sensitive. As per the naming convention standard, the first character of the variable name should be small letter. For example:
PurchLine purchLine

Data types

Primitive and composite data types are supported in X++. We can use EDT, table name, class name as data types. For example:
Name                    firstName, lastName;
PurchLIne            purchLine;
Access                  accessObject = new Access();

Multiple variable declaration

X++ allows you to add multiple variable declaration in the same declaration statement. For example:
int i,j;

real a = 5, b=3;

Sunday, March 15, 2015

Labels

What is label?

Labels in AX, is used to assign text to the objects ex. table fields. We can avoid to create duplicate text in label before create a new label by find the label in the label editor.
We should use labels for user interface text in forms and reports.

Label editor:

Label editor is an editor used to create, find, update and delete labels.
Open label editor:
In development workspace, Tools - > Label -> Label Editor


Create a label:

Open the label editor, click the new button and enter the text and description. Once you saved this label, the label id will create automatically the label id format will like @TES123. We can assign this label id to table field.


Assign label to the table fields:

Select the table field and go the properties window and select the label property, click the … button and enter the text, click the find button, the labels will come if the label already exist otherwise we need to create a new label.
If you know the label id then, we can directly enter the label id in the label property of the table field.




Use labels in the X++ code:

We can also use the labels in the x++ code.
For example: info('@SYS80122');

Use labels in the SSRS report:

We can use the AX labels in the AX SSRS report design. So, once we change label text in the AX label editor, it will automatically reflect in the SSRS report. Mention the label in the object expressions. For example: Lables!@SYS80122

Labels file:

The labels are stored in the label file. The label file is based on the language.
To create label files, Click Tools -> Wizards -> Label File Wizard
We can find the labels in the AOT -> Label files.

We can export and import this label files (.ald) to move the objects from one environment to another environment like development to production.

Tuesday, December 16, 2014

Form datasource find record method

Form datasource find record method

Form datasource find record method to find and set that record as current. So, the user can easily identify the record.

We need to pass the table record as parameter to this findrecord method.

Syntax:

public boolean findRecord(Common record)

For example:


Here, I have added some code in the button click method to find the record in the form datasource. So, that result record will be focused as current record.

void clicked()
{
    Hari_ExamResult examResult;
   
    select firstOnly1 * from examResult
    where examResult.StudentName == 'Hari';
   
    if(examResult)
    {
        Hari_ExamResult_ds.findRecord(examResult);
    }
    super();
}

Result:



Thanks,
Hari