Sunday, July 13, 2008

Dynamics AX Performance issue. Cross object references drawbacks.

Recently I'm working on framework for Dynamics AX 4.0. Project includes form tree control data viewing.

Basically tree framework includes class representing the whole tree and each tree node.
At first each tree node class instance (let's call it TreeItemClass) is associated with particular FormTreeItem storing reference to it (parmFormTreeItem()). Then reference to this instance is being stored in FormTreeItem.data() property.




The issue appeared when tree was built and I was trying to expand it's node containing a lot of sub nodes. Each time I expanded a new node, expanding time increased.
After throughly debugging I discovered that there were huge delays in object assignment.
Probably the problem was in garbage collector, which tried to calculate references.

Anyway, problem was solved by removing FormTreeItem reference from TreeItemClass and changing it to TreeItemIdx.

So be careful with cross object refernces in your code and try to avoid it.

Wednesday, July 2, 2008

CLR Interoperbility. Problem with Assembly Versions

If you're using CLR interoperability to access external logic, you can perform construct objectes two possible ways:

1. Add Reference and then construct needed object
Microsoft.Office.Interop.Outlook._Apllication appl = new Microsoft.Office.Interop.Outlook.ApllicationClass();

2. Also you can use
CLRObject appl = new CLRObject("Microsoft.Office.Interop.Outlook.ApllicationClass") ;

Using th first approach you're strictly tied to certain version of assembly. So, for instance, if user doesn't have Office 2007, assembly reference in DAX 4.0 will not be compiled, since certain 12th version is specified on it. So to be sure user will not receive this problem it's preferable to use second approach. How ever then you don't have an option to use .NET intelisence.

I'm looking forward fixing this issue in DAX 2009

Monday, June 2, 2008

Updating records without FORUDATE statement

I had an experience on previous project when I couldn't have inserted record in database because it was selected from another scope on server with forupdate parameter and then passed to another class to either insert or update it. Such kind of transfer was made due to abstraction of record initializer and to have the only place where record is written to DB.

The error saying that record was not selected for update was thrown.

But solution can be found in "Inside Dynamics AX" book.

The skipTTSCheck method can be called with parameter true on record in place where the record is written.
So by forcing skip of TTS check even record which was not selected for upadate can be written.

Though "last writer" rule applies here...
Anyway this record processing was expected to take place only from single machine at one concrete moment of time using batch processing.

.NET enumerations in Dynamics AX

As you know starting from DAX 4.0 .NET interoperability was introduced.
You can easily instantiate .NET classes either likewise COM or by directly calling constructor method:

Microsoft.Office.Interop.Outlook._Application outlookApplication =
new Microsoft.Office.Interop.Outlook.ApplicationClass();

it is the same with

Microsoft.Office.Interop.Outlook._Application outlookApplication =
new CLRObject("Microsoft.Office.Interop.Outlook.ApplicationClass");

Although usage of .NET objects is quiet common to COM, you cannot pass enum parameter to .NET object as int or str

Instead of doing it you have to initialize it this way:

Microsoft.Office.Interop.Outlook.OlItemType olAppointmentItem = CLRInterop::parseClrEnum('Microsoft.Office.Interop.Outlook.OlItemType',
'olAppointmentItem'
);

Here you're initializing type of new Outlook item with type Appointment.

This inconvenient trick should be held every time you want to initialize enum parameter. Anyway it is more convenient than defining macro values like is done for COM enumerations.