Dynamics Ax 2012 my ideal Azure VM setup

Introduction

This is just a quick note on how I setup an Ax 2012 on an Azure machine to get the most bang for my buck. The example I’m using is a DEV machine where I keep the sample code for this blog. But you could apply the principles for every environment.

Sizing & disks

Since I’m on a limited budget with my Visual Studio enterprise subscription I don’t use premium storage. So my favorites are the D2/D3 and D11 v2 machines, especially the D11 which has more memory, less cores (compared to D2/D3), it can have 4 data disks and the temporary local storage is larger than DS machines. This storage will become very useful for SQL Server and the extra memory is also a must.

Since standard disks are limited to 500 IOPS and 60 MB/s throughput I like to attach multiple disks and spread my installations over these. So I did my installation like this:

  • Disk 1: SQL service + SSMS + LDF files + backup folder.
  • Disk 2: SQL MDF files.
  • Disk 3: Dynamics Ax client and service + visual studio.

(You can even add a 4th disk on this machine size but I didn’t really need it.)

SQL Server

Another neat performance trick is to use the temporary local SSD for the SQL temp db and buffer pool extension file. Check the link below on how to do it, I also have modified their powershell startup script to start my AOS.

Source: https://blogs.technet.microsoft.com/dataplatforminsider/2014/09/25/using-ssds-in-azure-vms-to-store-sql-server-tempdb-and-buffer-pool-extensions/

Automation

I prefer starting and stopping my machine manually but another good way is to use Azure Automation to automatically start and stop your machine when you are not using it. This will save a lot of money on your bill.

https://docs.microsoft.com/en-us/azure/automation/automation-solution-vm-management

If this is too much trouble but you’re afraid that you might forget to shutdown your VM you can also use the auto-shutdown feature. This feature can be found on the menu of every VM.

Dynamics Ax RunBase overriding dialog with a Form

Hi,

Some time ago I’ve found out that you can implement a form into a RunBase dialog, this has the advantage that you can easily use a grid control, etc… or use modified field methods without using controlMethodOverload() method. You can do this by overriding the dialog method and adding the following code.

You can still add fields the normal way by using the addFieldValue() method, these fields will appear next to the embedded form.

This form must have a Tab control and some hardcoded groups, also on the design the property FrameType must be set to None. The groups I’ve created are DialogStartGrp and RightButtonGrp, these are used for positioning fields and query values from code. More groups may be necessary when extending from RunBaseBatch, RunBaseReport, …  The tab control is used for adding a batch tab when extending from RunBaseBatch.

Form example

In the dialogPostRun() method you can get the formRun of the dialog and make calls to the form, for example setting query ranges.

A way to pass data or do callbacks is to get the calling class in the form init.

Dynamics Ax printing logo’s from batch

Hi,

*Edit Microsoft has released a fix for this problem contact support for this*

As all of you know the Image class in Dynamics Ax 4.0 and 2009 can only run on client. This poses a problem when you want to print for example invoices with your company logo on it. Having this found out I went to look for an alternative!

I’ve added this code to the top of the PDFViewer class in the writeBitmap(OutputBitmapField _field, OuputSection _section) method

For the method BLOGWriteBitmapOnServer(OutputBitmapField _field, OuputSection _section) I have copied everything from the writeBitmap and started by replacing the Image object with a System.Drawing.Image object, you can make a company parameter for this file path.

After compiling there are a few errors witch I’ve corrected and ended up with this code.

This could probably been done much cleaner, but it does the job. 🙂

Dynamics Ax Reports with Calibri font

Hi,

A customer of mine asked me to change the font of some reports to Calibri. It all went well until we saved a report as PDF, there was way too much spacing between characters.

After some days of investigating and contact with Microsoft I’ve found out that it worked on a Windows Server 2008 R2 and the Calibri font files were almost double in size. So I replaced the font files with the ones from Windows Server 2008 R2 and the reports are working like a charm. 🙂

Dynamics ax take screenshots from FormControls

Hi all,

Here is a little code snippet for you to take screen shots within a Dynamics Ax client.

This snippets uses the size of your control and the position on your screen to create the screenshot 🙂

Dynamics Ax printing from the AOS

Hello,

This post will be all about printing from printers that are connected on the AOS instead of the client.

First up is installing a printer on the server thats hosts the AOS services. Next is configuring the client and server as shown in the next screenshots:

Client configuration
Client configuration
Server configuration
Server configuration

In the printer setup you should now be able to choose from printers with the prefix “AOS:”

*edit* : If the printer does not show up, try restarting the windows ‘Print Spooler’ service.

Many application object servers today are installed on 64bit operating systems this can cause problems when trying to connect a network printer that is hosted on a 32bit printer server. You might choose to upgrade the operating system of the printer server and face more drivers problems with other 32bit clients or install a secondary 64bit printer server, witch seems overkill.  A better is when the printer is connected directly to the LAN install it on the server thats hosts the AOS services. You can do this by installing the printer local with a TCP/IP port and using the 64bit driver.

Dynamics Ax SQL Trace

Hi there,

here is a simple job to enable SQL tracing for all your users, this quite handy for optimizing queries. (The macro’s for modifying other fields on the UserInfo table can be found on the ClassDeclaration of the SysUserSetup form.)

Make sure that client tracing is enabled in the server configuration. (Only use this in development and testing environments, tracing may affect the AOS performance.)

Server configuration
Server configuration

The results can be found in the Administration module.

SQL trace menu
SQL trace menu

Dynamics Ax RunBaseBatch multithreading

Hi,

Next post will be a little tutorial on how the RunBaseBatch framework can work multithreaded. For example in the SalesFormLetter class on the method run, the following code will be found before the query iteration:

The SalesFormLetterEndMultiThread that is being created will be called when all threads connected to that bacth are processed, this will call methods like printJournal and endUpdate. Notice that all the variables that are passed in the construct method are also  defined in the CurrentList macro for packing and unpacking, this is important to keep in mind when writing custom code.

In the iteration itself, another multithread batch task is created for each line.

So foreach SalesParmTable found an instance of the runtime task FormLetterMultiThread is created, and is a dependency for the SalesFormLetterEndMultiThread to run.

Now let’s create our own simple example.

Start by creating a RunBaseBatch class like you would otherwise do, but make sure that the code witch uses the most load is written in a separate method and called from the run. This method will be called from the threads. (method: updateSalesOrder)

Sales order update class

The canMultiThread method is the same as in the FormLetter class.

And the run method could be written like this, analog to the run of the SalesFormLetter class, but without an ending thread.

The second class you need to create is kind of a wrapper class that also extends from RunBaseBatch and will be used to create the subtasks for your batch process. Make sure that the runsImpersonated method returns true.

Sales order update multithread class

Remember that you need to keep an instance of the caller class (TSTSalesOrderUpdate) and you need to pack and unpack it.

The run method should call the updateSalesOrder on your TSTSalesOrderUpdate class. This means that all the logic is placed in one place, because it should also work when not running in batch. 😉

In addition you can add an ending multithread class if necessary, like the FormLetterEndMultiThread class.  The maximum number of simultaneous batch thread can be defined on the SysServerConfig form.

The example given is only for educational purposes. (It is somewhat sloppy 🙂 )

Dynamics Ax creating a batch job from code

Hi,

Here is a simple code snippet to create Batch jobs from code. This convenient when starting a heavy load job from a user interface and still keep the client responsive.

Dynamics Ax Creating sales orders with the SalesAutoCreate class

Many projects use an interface to import their sales orders, because of this a SalesAutoCreate class was created. This class is easily extendable and customizable.The first thing to do is designing a buffer table, like this one for example:

Sales order import table
Sales order import table

After this we can start extending a new class from the SalesAutoCreate class and modifying the construct on the SalesAutoCreateClass .

After the construct your buffer record should be passed in the new or a parm method could also be an option.

When extending from the SalesAutoCreate class some methods must be implemented:

  • setCust
  • salesType
  • recordExist
  • nextRecord
  • invoiceAccount

In my example I’ve implemented them like this:

The next step is setting our table and line fields by overriding the setSalesTable and setSalesLine methods and make sure that you always call the super first. Notice that you need to call the createSalesTable and createSalesLine to do the insert.

you should have a class looking like this.

Sales auto create class
Sales auto create class

the final step is to call the logic from a job or a RunBaseBatch class, make sure that you select records on the same tier as the nextRecord will run or else it will fail. Preferably on the server tier. 🙂

This example lacks some validation whether the record has already been processed or not, so it will created the same records every time it is called. You could implement your own method on the SalesAutoCreate class, call it from the create method and override it on your custom class, like this.

Dynamics Ax Cleaning up the AIF document log

While doing a small AIF project I wrote a small batch class to cleanup the AIF document log because the button on the AifDocumentHistory form can take up a huge amount of time. The first thing I did to write this class is checking out the standard Ax code in the following method ClassesAifMessageManagerclearAllProcessedAndError. This method uses a progress bar and deletes records in batches of 3000 records, this is something we don’t need when running in batch.

The first thing our method needs to do is check if we have access rights to delete.

The second step is requesting the permission to skip AOS validation.

The next step is calling all the skip methods, Microsoft does this to make sure that a delete_from doesn’t fall back to row by row deletes.

  • skipAosValidation : Skips all validation methods (validateWrite, validateDelete, validateField)
  • skipDatabaseLog : Prevents SQL from making transactions logs.
  • skipDataMethods : Forces doInsert, doUpdate instead of insert, update.
  • skipDeleteActions : Skips all actions defined under DeleteActions ( For example: Deleting a SalesTable also deletes all referencing MarkupTrans records. )
  • skipDeleteMethod : Forces doDelete instead of delete.
  • skipEvents : Disables a lot of kernel events to increase performance.

After these methods we can start deleting the records, I’ve used a utcDateTimeRemove variable to cleanup records after a certain number of days.

The final step is to revert the code access permission.

Source : msdn xRecord class

(this job should never run on a production environment, build an archiving alternative instead)

Dynamics Ax 2009 using the DateTimeUtil

Since i’m getting a lot of google hits on my Dynamics Ax – workdays to days post, i’ve decided to blog some more about it. The DateTimeUtil class is actually a wrapper of the .NET DateTime class.

A first thing to remember when using UtcDateTime EDT’s is that it is stored like the name says as Coordinated Universal Time.

The controls on the form will translate the DateTime to the timezone of the client. Now keeping this in mind is very important when mixing date, time and datetime controls. The following example will make it more clear.

The first field is a UtcDateTimeEdit control with a data method that returns DateTimeUtil::UtcNow().

DateTime debugger

As you can see the time is 08:58, but the first control on the form shows 10:58. This is correct because my client timezone is (GMT+01:00) Brussel, Kopenhagen, Madrid, Parijs and it’s summer time.

The second field is a TimeEdit control with a data method that returns DateTimeUtil::time(DateTimeUtil::utcNow()), this isn’t correct because it will always return the time in the UTC timezone and the control will not translate it to the correct timezone.

The third field is another TimeEdit control with a data method that returns TimeNow(), this is correct because the TimeNow method will also apply the client/server (depending on the tier) timezone.

this also applies to field in a table.

Datetime example
Datetime example

Another way to use Time controls and the DateTimeUtil is using the applyTimeZoneOffset method.

but this is a lot of code for a rather more simple thing 🙂

A second thing to remember, when querying with a date on UtcDateTime fields make sure you select the whole day from 00:00:00 to 23:59:59.

For this I like to implement a method on the Global class, it’s keeps you’re queries cleaner 😉 It works the same way as all .NET developers use, Add a with time 0 and subtract a second.

So you’re query looks like this.

Dynamics Ax modifying CreatedDateTime

For testing purposes with the MRP we needed to modify the createdDateTime fields in Dynamics Ax 2009. Since these are system fields we needed a workaround.

Remarks:

  • Make sure that it is running on the server tier
  • It only works on insert NOT on update

Since this code is pretty exotic and you don’t want to release this to a production environment we eventually didn’t use this but ran some sql jobs, but this shows that it is possible.

*edit*
Easy does it 😉

Dynamics ax a key with the name %1 already exists

Today I had to fix a bug in some custom code in Dynamics Ax 2009, we had an error from the JournalTransList class that stated “A key with the name %1 already exists.”

  • Cause: A custom field on the WMSJournalTrans table that was extending from LineNum
  • Reason: The JournalTransList has methods to check if the primary index on the actual table won’t be violated, therefore it seems to look for all fields that extend from LineNum.
  • Solution: Create you’re custom EDT that extends from LineNum and add that one to the table, it’s a best practice but who thought this could be so critical :p