Saturday, February 27, 2010

Impact Analysis feature for Dynamics AX 2009

Hot from the presses: Microsoft has just released a new tool, available from PartnerSource or CustomerSource, to analyze the impact of a patch on a system.

From the official text:

Impact analysis is the process of understanding a change that is being introduced into a system, determining the consequences of the change on related subsystems, and creating possible mitigation plans to reduce risk. When you install a Microsoft Dynamics AX 2009 hotfix, impact analysis consists of understanding the changes being made to application objects in the SYP and GLP layers, analyzing how these application objects are customized in the environment, and creating test plans to test the system after you install the hotfix.

In theory, this sounds very good. Very anxious to test this out, definitely worth a try. Hope it is as good as it sounds.

With a new hotfix rollup under way (Rollup 4 for Ax 2009 is expected first half of March 2010), this could be very usefull.
We've all been in that kind of situation: Where the only solution left was to install a hotfix, but you didn't know if it didn't create more troubles on the way.
I would have expected a tool like this when Ax 2009 came out, but better late then never.

Friday, February 26, 2010

How to get a label in a different language

The tasks seems easy enough: How the get a specific label in a different language.
(Remember my post, 'How to set the language used on a report')

Now we only need to retrieve the text for one label id, in any given language. Going through the help files of Ax, you come across this class SysLabel. It contains the labelid2String method.

Example:

info(SysLabel::labelId2String2("@SYS87980","de"));

Only... This does not work like that. Didn't work in Ax 4.0, doesn't work in Ax 2009. You always get the label back in the language that's been setup for the current user, no matter which language you specify in the call to this function.

Luckily, there's an easy workaround, tricking Ax: Split up your label id. Like this:

info(SysLabel::labelId2String2("@"+"SYS87980","de"));

Credits: With thanx to this blog for this simple but yet very effective solution.

Edit: SysDictCoder pointed out a nicer solution in the comments, by using literalstr.

info(SysLabel::labelId2String2(literalstr("@SYS87980"),"de"));

Wednesday, February 24, 2010

How to get the biggest value (retrieve the greater figure)

If you ever needed the greatest value of 2 variables and wrote an if-then-else statement, there is a simpler solution. Ax has a built-in function to determine the maximum value in a range of variables, namely max.

The use: max(anytype var1,anytype var2);

Where var can be an integer, real, ...

Example:


static void MyMaxJob(Args _args)
{ int test;
int var1=200,var2=300;
;

test = max (var1,var2);

info(int2str(test));
}


Now the documentation suggests this only works with 2 values (or figures), but in practice you can use more values as well. Like this:

static void MyMaxJob(Args _args)
{ int test;
;

test = max (100,1200,300,400,500);

info(int2str(test));
}

This sure gives nicer code that those if-then-else statements, not?

Of course, there is a counterpart function as well for finding the smallest (or lesser) values, min.

(Minus 200, or -200, is smaller than 100. So it's not the absolute value that is taken into account!)

Friday, February 19, 2010

Internal error number 174 found in script

Another blog post title for this one could be 'How to crash your AOS server in 1 easy step'. Because that is what we'll be doing in this post!

So be warned and take care if you wanna test the code on this blog. As always, it's your responsibility.
Anyway. We experienced some AOS crashes in our environment and started to investigate the cause. We could trace the crash to some specific code. When executed, we got following error in a dialog box on the client:

Internal error number 174 found in script

And with that, the AOS service died on us.
The application event log of the AOS server reported a 'Faulting application Ax32Serv.Exe' error, with event id 1000.

The code to simulate:

static void CrashAOS(Args _args)
{ SalesLine SalesLine;
SalesId SalesId='xyz';
;

update_recordset SalesLine
setting LineNum=-SalesLine.LineNum
where SalesLine.SalesId==SalesId;

return;
}


Looks like Ax didn't like what we tried to do with the update_recordset statement.
We ended up recoding, replacing the update_recordset statement with a select forupdate statement.
(Note: This code didn't give problems in old Ax versions, but it did in Ax 2009.)

Thursday, February 11, 2010

Recordcount and recordsize

In my last post, I talked about tables and how they can grow over time.
Now there are 2 elements that matter:
  • the number of records in a table
  • the size of a record in a table

It's fairly easy to keep track of both them, by using the SysDictTable class.

The number of records in a table? Use method recordCount

static void RecordCount(Args _args)

{ SysDictTable dictTable;

;
dictTable = new SysDictTable(tablenum(CustTable));



info(strfmt('Table %1 has %2 records',dictTable.name(),int2str(dictTable.recordCount())));

}



The size of a record in a table? Use method recordsize


static void RecordSize(Args _args)

{ SysDictTable dictTable;

;
dictTable = new SysDictTable(tablenum(CustTable));



info(strfmt('One record of table %1 has this size: %2',dictTable.name(),num2str(dictTable.recordSize(),0,0,1,0)));

}


The method recordsize just iterates over all the table fields, summing up their size.

Now their is a funny thing with method recordcount. This function returns a value of type integer. Now in the old days, record id's of Ax were integer values. But they reached the limitation of that, so decided to uplift the record id's to type int64. But still, the function recordcount is limited to giving back integer values, so your maximum count will be 2 147 483 647 (the value of maxint()).


There's always room for improvement, the need for an upgrade...

It's not Big, it's Large

The database of every Ax installation will grow over time. How fast? Depends on the activity.
Which modules our active? How many transactions are created? Do you have 10 invoices a day, or a 1000 a day. Many different factors influence the data growth.

You can check which tables occupy the most space in your database. Ax has an out-of-the box report to do some follow up. You can find it under Admin - Reports - Size of company accounts.

This report gives detailed on all the database tables, with a record count and an estimated size used.
The outcome may stimulate you to clean up some old data, and allows you to focus on the right direction as well. (Again, Ax has some built-in functionality for that also.)

Also, be on to lookout for not so obvious suspects responsisble for excessive growth in database volume. Like table SysTraceTableSQL. On our installation, it had grown to several gigabytes over the years, claiming way to many disk space.
This system table stores information about trace events. You can purge the old data if you want, after you've done analyzing it. (Be carefull with your timing though, as deleting a table of several gigabyte can stall your database server.)



(Oh and yes, this blog post title was lent from Lyle Lovett.)