Rather than a company having separate software applications for accounting, sales, manufacturing, inventory, and other systems; an ERP system is one software program that integrates all activities of the business in one system.
If not developed right, an ERP systems codebase can quickly become complex to maintain and add to. One of AX’s strong starting points is that it can achieve a lot of functionality with very little code.
In the book 'Inside Microsoft Dynamics AX 2012' the original people who worked on early versions of AX were asked: “How was the idea of using X++ as the programming language for Microsoft Dynamics AX conceived?”
“We had been working with an upgraded version of XAL for a while called OO XAL back in 1996/1997. At some point in time, we stopped and reviewed our approach and looked at other new languages like Java. After working one long night, I decided that our approach had to change to align with the latest trends in programming languages, and we started with X++.”
Erik Damgaard - Cofounder of Damgaard Data
Of course, the developers had several perspectives on this breakthrough event:
“One morning when we came to work, nothing was working. Later in the morning, we realized that we had changed programming languages! But we did not have any tools, so for months we were programming in Notepad without compiler or editor support.”
The developers of AX managed to create a system that took object orientated programming to a new level. AX featured:
a tightly integrated database that automatically updates its schema
a query engine for simplifying SQL queries and data access in code
extended data types so fields can be defined once then used across multiple tables
field groups can be defined once and used across multiple forms
automatic form layout, data binding on fields and labels retrieved from data model
an object orientated data model. Tables, datasources and datasource fields are objects that can have their own methods defined.
built in reporting engine that is aware of data model
All this and more helped keep the code base to a minimum.
With different industries requiring different customizations to their systems, AX lead the way with its simplicity. For example, if a company wants a modification to store 'drink preferences' for each of their customers a developer would need to :
Add a new field to custTable defining a Name, Label and String size
Drag the new field onto an existing field group in the custTable
After this the database schema will automatically be updated to include the new field (no manually writing sql patch files). The field will automatically be shown on any forms using the dataGroup that the field was added to (no form design modifications needed). All the AX clients automatically get the latest code from the server so when users open the customers form they will see the new field and be able to use it (no client code deployments needed). The new field is also automatically integrated into AX's query engine allowing the user to filter or sort customers by their 'drink preference'. This ease of customization has been a big selling point for AX.
From Axapta 3
The year is 2002, desktop computers were running Windows XP, the latest hardware was a 2 GHz Pentium 4, Battlefield 1942 was released, and Microsoft also releases their first version of Axapta since they acquired it from Navision-Damgaard.
Ease to path and upgrade
AX’s code model is built on layers, effectively keeping customized code separated from the code released with the application. During upgrades any code conflicts can be automatically detected. Resolving conflicting code has always been a manual process however AX has the tools to compare the old and new released code, and the customized code. Layers have also been useful for regional customizations and 3rd party add-ons, as a layer only includes objects that have been modified and it keeps the code separated for comparisons.
The above image illustrates the comparison tool comparing Microsofts released code with customized code of the CustTable table. It identifies the new 'Drink preference' field and field group change made earlier.
When developing a large integrated system changing one object can affect many other places, the AX cross reference tool can find all code which references a method, field, or object. It’s a very handy tool to have when customizing a large existing codebase.
In the example earlier where 'Drink preference' was added to a field group on the customer table, it would be useful to know which forms and reports this change has affected. By right clicking on the new field and choosing 'used by', a form will open showing all the places in the system that reference the field. We can see from above that along with the Customers form, the Telemarketing form will also display this new field.
Cross reference can be very useful for finding code that writes to a field or table since the reference column can be filtered to only show 'writes'. Also it can be handy to find all code that calls a certain method.
Form controls are arranged automatically, AX uses the label and field length properties from the data dictionary to determine how a field should look. Field are grouped into field groups and and are arranged into columns on the form. Experienced developers won’t even look at the form designer when designing a form. Controls can be added to the forms design node in a tree like manner and AX will automatically perform the form layout. A fair amount of form development can be done just by clicking and dragging objects around, tables can be dragged onto the forms datasources, and then field groups from the datasources can be dragged onto the forms design node, also a related forms menuitem can be dragged onto the design to create a button. Labels for fields are already defined at the data model level but can be overridden on the form if needed. Based on the users security access, controls will be hidden if the user does not have the correct privileges.
The 'Drink preference' field highlighted above was automatically added to the customers form when the field group on the table was changed because the 'customer' field group on the form has its 'auto data group' property set to 'yes'.
Powerful form query and controls
The grid control on forms allowed sorting by clicking on the column headers, right click to filter by the selected field, autosizing of columns. Form controls are binded with datasource and field properties such as allowEdit or mandatory. Child datasources can be automatically linked to parent datasources to update the query when the parent record changes.
It is possible to quickly navigate to a fields related form using the right click context menu and choosing ‘go to main table’ function. For example if there is an item on a sales order and you wanted to open the items main form. http://www.axaptapedia.com/Go_To_Main_Table
Fields on forms that are linked to an extended data type which is a key field in a table will automatically become a Lookup field. For example, adding a field with the extended data type of "itemId" to a form will automatically add a drop down to the field so the user can lookup and select an itemid.
Database log could be turned on for any table to track which user has changed data and when. For example database log could be enabled for custTable, then after there have been changes to a customers information or settings, the database log can be filtered to show how the customers record has changed over time.
Dynamics AX 4
The year is 2006, Microsoft was working hard on completing their great new operating system 'Windows Vista', Intel had released 3GHz dual core cpus, Half-Life 2: Episode One was released, and Microsoft also releases their first major revamp of Dynamics AX.
Main menu has been redesigned and docked to the side of the main application window. It now includes a favorites area where users can add commonly used forms and also specify how the data should be filtered when the forms open. For example a user could create a favorite link to the Sales Orders form that also filters the grid to only show orders for the customer named "Desk world", they could then name this favorite as "Desk world orders".
Good bye 2-tier client. AX could once support running clients without an AOS. The client would connect directly to the database. Although 2-teir worked much faster than going through the AOS (3-teir), it also opened up a large security issue where the database login would be stored in the client configuration.
Code access permissions for code running on the AOS. Restrictions were added to certain methods running on the AOS that could cause a security threat. For example, classes such as FileIoPermission were created to allow access for the AOS to write to a file on the server. The class would need to be called by code running on the AOS to allow access. This means that a compromised client would not be able to tell the AOS to write to the file system.
Version control and TFS integration. Microsoft added integration to their version control system (at the time called Visual Source Safe), this gave developers a view of what code has changed over time and the ability to roll back changes, where typically developers would need to take a backup of the project before making changes. The downside of using this is that developers need individual aos instances rather than sharing a single development aos, and this adds to maintenance overhead and introduces issues with table id conflicts. An ID server was introduced to be able to allocate unique object id's to multiple development environments without causing conflicts.
Basically allows you to write .net code and use .net components from within x++ code.
AIF – A framework for building data interfaces between AX and other systems, however it is limited to using XML files with a very strict structure.
Recids were changed from 32bit to 64bit since some companies where hitting the limit of 4,294,967,296 records. There was actually a tool in the older AX to renumber the recids to make more space.
Active directory now required. In AX 3.0 users could log in to the client using a username and password. This allowed them to log in to the AX client from locations outside the office, such as using a laptop connected to the internet at a customer’s site. Companies could even give 3rd parties access to their AX system by just providing a client installer, client config, and username and password. With the new Active Directory requirement, companies that span multiple sites that didn’t use a single active directory are no longer able to use the AX client across their other sites, companies can no longer give 3rd parties access to use AX client. The workaround here has been to use remote desktop to connect to a terminal server on the domain. Forcing active directory integration has increased security for AX greatly since all computers on the domain can have a domain security policy enforced, however it has also greatly restricted the uses of AX. This change benefits larger organizations but can be a problem for small companies.
.net business connector
Lets you call x++ methods and read/write ax data from visual studio. Essentially it is a AX client without a GUI.
Dynamics AX 2009
The year is 2008, disgruntled desktop users were reverting from Windows Vista back to Windows XP, Grand Theft Auto IV was topping the game charts, and Microsoft also releases AX 2009.
Shown as the home page when you open AX, charts from enterprise portal and analysis services give an overview of company performance and kpi’s. This was typically used as a selling point in sales demonstrations but not often implemented because of licencing and setup costs. Back in 2009 most laptops only supported 4GB of Memory and had slow harddrives making it difficult to do a presentation of the Role Centers running on a laptop.
The main menu is now shown as an area page in the main window, the side menu will only show links to list pages that open in the main window.
When working with AX, many windows can be opened when navigating through the system. List pages fixes that by providing a more browser like navigation where a new window won’t be opened, it provides back button and a breadcrumb bar. Double clicking on an item in the list page will open the related form for that item. List pages include a new filter bar that is integrated into the kernel and cannot be customised by a developer. Apart from looking nice and having predefined filters, list pages didn't offer any new functionality. Users could turn on 'show forms in navigation pane' and navigate directly to the forms rather than going through the list pages.
Action pane and action buttons
This change brought about the Microsoft Word style buttons for AX. Typically form buttons were plain buttons with labels. The action pane is used on list pages and categorises buttons into tabs and groups, most buttons now have icons next to them bringing a more modern look and feel to AX. Developers now have a many more embedded icons to choose from to use on buttons.
Forms now open outside the main applications container; new windows show up in the windows taskbar. Each window now has its own toolbar and can be maximized to take up the full screen.
Global address book (DirPartyTable)
This is a global repository of people and organisations (called parties). When creating a customer or vendor, a party record will be automatically created to store the organisations details. A single Global Address Book record can be linked to customers, vendors, business relations, employees and other global address book records. The advantage here is that if an organisation is used as both a customer and a vendor the user can see all the relationships, this can also store how a single person can have relationships with different organisations. The contact details of the organisation can be stored and updated in one place so are easier to maintain. Although later on it has been recommended to create separate party records if dealing with different departments in the same organisation since the contact information between departments are usually different. Linking tables with a valid date time stamp were used so its possible to see a history of how contactInfo, addresses and relationships with other parties changed over time. This change to the application introduced more complexity to the data structure.
Crosscompany queries. Previously the only way to read data from another company (dataareaid) was by using the changeCompany function.
Datetime data type adds timezone support. This is a big improvement for companies which have sites across different time zones. Also it makes sorting and filtering data by date and time much easier.
This is quite powerful functionality in AX which allows users to set up notifications for when data changes or if when date field becomes equal to the system date +/- a number of days.
The user can right click on any field in the system that is bound to a datasource and click 'Create alert rule'. Filters can be defined to only receive alerts for a specific set of records. Different events can be specified depending on the datatype, some examples are: 'has increased above amount', 'is set to', 'record has been deleted', 'is due in'.
The year is 2014, Windows 8 users were still trying to find their start menu, Intel had released their 4 core i7 series at 3.5GHz. South Park fans had a new video game - South Park: The Stick of Truth, people were aligning colored candies on their phones and Microsoft also releases AX 2012 R3.
AX2012 is a much larger and more complex application, continuing the focus on larger corporations and leaving a gap in the ERP market for smaller companies where more simple solutions such as Xero can take hold.
Many action pane buttons are replicated across multiple forms, and parameters such as icon, label and text are stored against the button. Having redundancies is not really the way of ax and this could have been designed a bit better. A better design would be if the data dictionary was updated to allow defining menu items for each table, then on the form the menuItem could be dragged from the form datasource to the actionPane. It seems like for now they are just copying and pasting the buttons between forms.
Code base and labels moved from file system to database
The application codebase for ax has traditionally been stored on the filesystem in ‘.aod’ files. Deployments to production would typically be done by copying in new ‘.aod’ files. If using multiple AOS’s these files could be kept on a single fileshare so each AOS always sees the same codebase. In AX2012 the application codebase was shifted into the database, initially it shared the same database as the data and then was later shifted out to its own modelstore database. Deployments could be done by using AX Powershell and command line tools to import model files. To allow the latest code to be compared with previous versions a baseline database can also be specified in the AOS configuration which can be a previous version of the modelstore database, this works similar to placing .aod files in the ‘old’ folder in previous versions of AX. Backups of the modelstore database can be scheduled using SQL server agent and this provides a single method for backing up both data and code. Some performance decrease can be seen from this new architecture when expanding treenodes in the AOT or when searching through the AOT. Labels which were stored in .ald files and usually can now be viewed and edited in the AOT.
Traditionally X++ has been an interpreted language, this means that the AX kernel reads the X++ at runtime and performs its own operations to execute the code. This has advantages for dynamic languages where code can change at runtime. A good example of this is in the AX forms where fields are added based on what is in the tables field groups, or when code changes are performed on a live system without taking it offline.
AX 2012 introduces a CIL compiler which allows code to be compiled to a state where it can then be directly executed by the machine. CIL code can execute at a rate 30X faster than interpreted x++, speed increases are only seen where the code is not dependent on waiting for the SQL database. Operations that are cpu intensive such as code comparison, master planning calculations and price calculations are noticeably quicker when running in CIL. Unlike interpreted languages, for the CIL to compile there must be no code errors in the entire application, a single error will mean the entire CIL compile will fail. If a developer makes changes to the code but does not compile the CIL, then the code changes would not take effect for code running in CIL. Once a full CIL compile has been completed successfully an incremental compile can be done to only compile changed code, this is much faster than a full CIL however it will also restart the AIF webservices. The CIL compiler can sometimes give odd error messages and also code running in CIL can give unusual error messages or none at all if something goes wrong.
Entire application compiled into Dynamics.Ax.Application.dll file and .netmodule files.
Because of differences in the compilers code running in x++ and code running in CIL have slight differences in the way they execute some logic.
CIL code can be debugged in visual studio by opening the code in application explorer, setting breakpoints, then attaching to ax32serv.exe process.
The compiled CIL code is stored in the modelstore database and written to the AX install path each time the AOS restarts. In environments with multiple AOS’s, all AOS will need to be restarted after a code change. The aos service will take longer to start since it needs to read the CIL from the modelstore database.
Different from SQL partitions. AX partitions were introduced as a level of data segregation in AX above the dataAreaId level. Since more and more tables in the application are becoming crosscompany some organisations needed a way to better keep data separated between their legal entities. This can also save on licencing and hardware costs since resources can be shared. All partitions will share the same codebase and database. PartitionId is automatically added to table indexs along with the dataareaid, so when filtering and joining tables without using the ax query engine the joins should always include partitionId and dataareaId. The users table is also per partition so different users can be added to different partitions.
This is basically where related tables are joined using RecIds rather than using custom Id fields. The refRecid to the related table will be stored in the database but when shown on the form, the kernel will replace the recId value with the 'replacement key field' specified for the related table.
The example above shows how the unit conversion data is stored in the database, the FromUnitOfMeasure field is a reference to the recId field on the UnitOfMeasure table. In AX when the field is displayed on the form AX has automatically replaced the recId value with the actual unit id from the UnitOfMeasure table.
This is a good concept since it takes less space to store a RecID field than a string field in the database, and is much faster for SQL to index and do joins on.
I had a better look into how AX was doing this and found that AX will add a left join to the main query, joining to the unitOfMeasure table to return the additional value. In the Unit Conversion form above, AX automatically adds two additional datasources to the form, one for 'From unit', and one for 'To unit'. These datasources are 'outer joined' to the main datasource. The replacement key fields can be filtered or sorted as if they were on the main table, filtering by a replacement key field will add the filter to the related table.
Above shows the foreign key replacements for the customers form. In the form customization the fk replacement datasources are prefixed with 'Ref_tableName_'. These can also be seen in the advanced filter screen on the form, not all the fk datasources where joined to the query here because of the localization settings on the extended data types.
Using foreign key replacement throughout the system may slow things down a bit (from there being so many additional datasources on the form). Microsoft has only recommended this for when building new tables, most of the existing tables in the system have not been updated to use foreign key replacement.
In AX2012 the table structure has been normalized, this means storing more data in joined tables rather than having a single table with many columns. There is a heap of advantages and disadvantages for table normalization. I'll use a one specific example to highlight these, however they can be generalized across the whole application.
In AX2009 customer contact information is stored directly on the custTable. (denormalized or flat)
In AX2012 customer contact information is stored in the LogisticsElectronicAddress table which is linked to the custTable. (Normalized)
Functionality: With the flat view in ax 2009 the user can only store one contact email per customer, if the organisation has a requirement that they need to store two emails for a customer then they would need to get a developer to make a modification to the custTable to add an additional field. In AX2012, the normalized table structure already allows many email addresses added for one customer and no customization of the system is needed. One piece of functionality that is lost with table normilization however is the ability to filter and sort on fields that have been normalized. In AX 2009 a user could right click on the customers email field and click filter to search for a customer by email. This is no longer the case in AX2012 as the field is now in a joined table.
Usability: In AX2009 to add an email address to the customer a user would just need to fill in the email field on the customers form. For AX 2012 the user would need to create a new contact information record on the customers form and then select the type "email" and then fill in the email address.
Customization: Table normalization adds more complexity to the code for dataaccess, for developers accessing or writing to normalized data requires a few additional steps. More table joins are required to get to the table needed, and also additional logic for if a record should be inserted or updated. Reading data out of AX can also be more complex if the output is expected in a flat format.
Performance: Table normalization has been a big hit on the performance of AX. Firstly, for fetching data from code is typically done per table so it adds more round trips between the AOS and SQL. Also table normalization adds more datasources to forms which has a big impact on the UI performance as it creates many more round trips to the server.
Locking: Less update conflicts, but more deadlocks. In AX2009 if two different users opened up the Customers Form for the same customer, then one user updates the email address and clicks save, then the other user updates the name and clicks save an ‘update conflict’ exception will occur for the second user because the first user has changed the record. In AX2012 the normalized table structure means that the table that the email address is stored in is different to the table that the customer name is stored in and no update conflict will occur. Update conflicts are usually easy to resolve however deadlocks which would usually occur in batch processes can be much harder to fix. AX2012 makes deadlocks more likely as the normalized structure means more tables and records need to be updated and locked in sequence between a ttsbegin and ttscommit. Quoting from Subhro’s blog:
“Due to excessive normalization of the database most transactions involve multiple joins which holds locks on multiple tables, which automatically increases the chances of blocking and deadlocks. In this situation, Denormalizing the tables can reduce the number of deadlocks.”
Tables in the AOT can now have a parent - child relationship, child tables include all fields from the parent table plus any fields defined for the child table. In the database this is stored as one large table with all the fields of child tables and the parent table together. Where the fields are not relevant to the record type they are left as null in the database. Indexes on child tables are created as filtered indexes to only include the appropriate rows.
All X++ reports have been rebuilt in SSRS, the time needed to develop or modify reports is greatly increased. The main advantage with SSRS is that it allows integrated charts, where x++ reports had to use a generated image to display charts.
Rather than the reports being internally generated from AX, there is now an interface that sends all the data needed to SSRS to render the report. SSRS must be installed with the SQL server installation. Visual studio must be installed and then AX report tools installed to edit reports, Reporting server configuration can be setup in System Administration / report servers.
Traditional AX reports worked a bit like forms, they had a datasource which could either be a AOT query or could be defined on the report. When the report runs it initially calls a prompt method to get inputs from the user, it then calls the fetch method which executes the query and calls the send(common) method for each row that the query returns. Each time the send method is called a report section is rendered. Both the fetch and send method can be overridden to customise behaviour, also the executeSection() method on each report section can be overridden to customise behaviour. Elements in a report section have a fixed position unless updated through code. Reports are drawn from top to bottom using the full width of the page, Prologue, Page header, Programmable sections, Section Header, Section Body, Section Footer, Page Footer, Epilogue. AX included a report designer view where the report layout could be viewed and changed by dragging around elements however much like the form designer this was more used as a preview than an editor since moving controls in the designer would change the controls positions from auto to fixed and cause problems with the layout. Common report outputs used were screen, printer and pdf. Html output was supported but did not render so well.
Advantages of AX reporting:
Aware of datatypes length and labels
Built in code comparison for upgrades
No deployment to reporting server needed
Report can be automatically scaled to fit the page
Data can be reported directly from the database
Integrated business logic and can use display methods
Sections can be shown or hidden based on configuration or region code
SSRS reports work by a class in AX executing a query to fill a temporary SQL table, a reference to the table is passed to SSRS to be able to read the data. About 7000 additional tempDB tables have been added to AX to support the new SSRS reports.
MorphX Reports - Entire report can be defined as one object in AOT
SSRS Reports - DataContract and TempTables need to be built to pass data to SSRS
In SSRS even simple fields are usually a complex expression
AX2012 now requires a bunch of hotfixes to be downloaded and installed from Microsoft before it can be installed. The installer will guide you through what is needed but it is a good idea to keep all these files ready for the next time you do an install.
Introduced as a way for vendors to keep objects in their solutions separate from other objects in the same layer. An object in a layer can belong to only one model. Typically this used to be done by prefixing the objects name with a 3 letter code.
Table / Field Id's
Export / Import with Id values has been removed. AX uses internal id values to reference tables and fields, the id's are stored in the model database along with the codebase where references to the id's are also stored in the data database.
This system worked well when there is a single development AOS which all changes are done on first, then projects or layers are exported with id's and imported with id's to the test / production environment. Table and field id's would always be in sync across all environments. If a developer renamed a table or field in the development environment then imported the project into the test environment, the renamed fields would still have the same id's so AX would rename the fields.
If developers are using separate AOS's and a developer deployed a project to production with table changes and the 'Import with field ids' checked then they are pretty much guaranteed to run into problems. When ax tries to synchronize the tables with conflicting id's it can end up dropping the entire table and losing all the data. This is probably why the option was removed, however it was quite useful to have if you know what you are doing.
The milky white screen
In the older versions of AX during long processes in the status bar there is a status indicator which indicates client / aos processing and data transfer between Client and AOS. In AX2012 the screen will just turn 'milky white' and give no status indicators after processing for a long time.
Microsoft provides the ability to spin up demo environments, and high availability environments in Azure with just a few clicks. Because the AX2012 client is quite 'chatty' with the AOS, the AX clients can run from a Remote Desktop Services server in azure and users can connect via remote desktop or remoteApp.