Most performant way of concatenating strings in Microsoft Dynamics AX

I was recently asked: “What is the most performant way of concatenating strings in AX?”

Traditionally there have been two approaches to build and/or format strings in AX, strFmt and + ing, but you can also leverage the .NET libraries like System.String.Concat and System.Text.StringBuilder.

In this scenario, the goal was to build up a string of a fixed set of elements:

strFmt
str ss = strFmt('Context=%1, Activity=%2, ActivityId=%3, Type=Stop, Tag1=%6, Tag2=%7, Tag3=%8, Tag4=%9', context, activity, activityId, tag1, tag2, tag3, tag4);
+ ing
str ss = 'Context=' + context + ', Activity=' + activity + ', ActivityId=' + activityId + ', Type=Stop, Tag1=' + tag1 + ', Tag2=' + tag2 + ', Tag3=' + tag3 + ', Tag4=' + tag4;
System.String::Concat
System.String s1 = System.String::Concat('Context=', context, ', Activity=', activity);
System.String s2 = System.String::Concat(', ActivityId=', activityId, 'Type=Stop, tag1=%', tag1);
System.String s3 = System.String::Concat(', tag2=', tag2, ', tag3=', tag3);
System.String s4 = System.String::Concat(s2, s3, ', tag4=', tag4);
str s5 = System.String::Concat(s1, s4);
System.Text.StringBuilder
System.Text.StringBuilder sb = new System.Text.StringBuilder();
   
sb.Append("Context=");
sb.Append(context);
sb.Append(", Activity=");
sb.Append(activity);
sb.Append(", ActivityId=");
sb.Append(activityId);
sb.Append(", Type=Stop, tag1=");
sb.Append(tag1);
sb.Append(", tag2=");
sb.Append(tag2);
sb.Append(", tag3=");
sb.Append(tag3);
sb.Append(", tag4=");
sb.Append(tag4);

str result = sb.ToString();

And the results …

Unboxing Dell u3417w Widescreen (3440 x 1440, 21:9)

After having lived in our new house for more than a year, I have finally gotten around to setup the home office.

For that I needed a decent desk and monitor setup. For the past 13 years at work I have been using a dual or triple monitor setup, so this was my initial thought for the home office as well.

However when I started researching the market, I came across these “new” widescreen monitors with 3440 x 1440 solution and a 21:9 format.

To cut to the chase I ended up with buying the Dell u3417w, due to budget and Dell’s 3 year warranty.

In the coming months I will be using for professional development and write a review based on my experience.

Microsoft Dynamics AX 2012 Product Configuration : Enterprise Portal

In this blog post I will explain how on user interactions are handled by the product configuration module for Microsoft Dynamics AX 2012 on the Enterprise portal.

EP_1

 

 

The figure above, is a high level illustration of how user interactions in general are processed on the Enterprise Portal (EP) for Microsoft Dynamics AX 2012. The clients access the AOS through EP, which is a web implementation built on top of Microsoft Sharepoint, hosted on a web server (IIS). The communication between EP and the AOS is synchronous using the .NET Business Connector RPC call. Each RPC call must be completed and returned, before http request timeout is exceed on the IIS.

To understand what implications the above has, when using the Product configuration module, we will go through the sequence of events, which take place when the user loads a configuration model and assigns a value to an attribute.SequenceDiagram_EP

The above illustrates the sequence of loading a configuration model and assigning an attribute a value on the Enterprise portal.

 

Loading a configuration model

 

When the user wants to configure a product, e.g. from a sales order, the requests will be handled by EP.  The EPPCConfigurator web control will be loaded, inside the web control a proxy Instance of the PCEnterprisePortalMain class is created. This proxy is used to interact with the AOS Product configuration logic.

On the AOS, the XML representation for the specific configuration model is retrieved from the database. Then the XML string is passed as argument to Product Configuration Server API, which unlike the Client API is design to support synchronous execution. In the creation of the ProductConfigurationServer instance, the XML is parsed and supporting data structures are created, just like on the Windows client implementation.

 

Once the data structures have been created, the configurator instance can start processing the constraints and calculations of the configuration model. Unlike the Windows client however, the processing on EP needs to respect a fixed time limit, in order not to cause a timeout on the web server.

 

Another difference between the Windows client an EP is the way the model is being processed. The EP implementation will attempt populate all visible enumeration and Boolean attributes. This is the equivalent of opening all the visible attribute controls on the active component in the form, and letting the configurator deduce feasibility of the values of each attribute.

The more attributes that are visible, the less time that is available to process each attribute. For components with over 20 enumeration and boolean attributes, it can happen that there is not enough time to process the feasibility of all values within the domain of the attribute.

 

Assigning values to attributes

When the user   makes an assignment to an attribute, the web form is then posted back to EP and  a request to assign the attribute is made on to the AOS. On the AOS, each call from EP executes in its own context, this implies that a new instance of the configurator is created. This instance must again parse the XML representation of the configuration model, before being able to process the user assignment. After this, the instance is disposed and a new one is created to process the assignment , same as before.

 

The main problem can be seen from the diagram in Figure 2, is the activation line of the ProductConfigurationServer object. Unlike the Windows client implementation , the configurator instance is not kept alive throughout the configuration session. The synchronous execution combined with the time limitation is the main limiting factor, which forces us to create and dispose instances of the configurator for each request.

 

The consequence of this is that the EP implementation of the configuration module, is not able to deliver a user experience which is similar to that of the Windows client for models of medium to high complexity.

 

Please keep this in mind when considering implementations of the Product Configuration module on Enterprise Portal for Microsoft Dynamics AX 2012.

 

 

 

 

Microsoft Dynamics AX 2012 Product Configuration: Windows client processing

In this blog post I will elaborate on the processing of configuration models in Microsoft Dynamics AX 2012 R2 and R3.

Win1

Figure 1

Client 1 loads a configuration model using an RPC call to the AOS to retrieve an XML representation of the configuration model. After this the processing of the configuration session happens on the client.

When Client 2 wants to load a configuration model, it goes through the same process as Client 1, by retrieving its own XML representation of the configuration model, which it wants to load. Then processing of this model happens solely on Client 2. In this way processing is distributed on the hardware of the different clients.

However, the reality for many of our customers and partners is a bit different to the picture shown Figure 1.

Win2

Figure 2

The setup in Figure 2 should be more familiar to those of you who have experience with Microsoft Dynamics AX 2012. Instead of having fat clients as in Figure 1, the users are instead connecting to the Dynamics AX windows client, using a remote desktop session, set up on a Windows server running Terminal services.

Thus when Client 1 wants to load a configuration model, it happens via the Terminal service, which is then retrieving the XML representation of the configuration model from the AOS. The processing of the configuration session then happens in the context of the remote desktop session, which is on the host of the terminal services.

The same thing repeats itself when Client 2 wants to load a configuration model. The difference between this and the previous setup is, that processing for both configuration sessions are now centralized on the host of Terminal services. This processing includes not only the processing of the underlying configuration model, but also the processing related to handling the rendering of the UI.

When we look at what is happening at a lower level, with more details, the picture looks like this:

Win3

Figure 3

The diagram in Figure 3 shows what happens when the XML representation of the configuration model has already been retrieved from the AOS. From the Xpp client it is then passed on to the Product Configuration .NET component crossing the CLR interop. In the loading phase of the configuration model inside the .NET component, the following action are executed:

  • Parsing the XML representation of the configuration model
  • Creation of supporting data structures

After these processes the .NET component starts to process the loaded model and then starts to issue events whenever it is able to deduce that an attribute must take on a certain value. These events are send back to the Xpp client which updates the page accordingly.

At some point the user will want to accept the configuration and this is done by pressing the OK button on the dialog. When this happens a method is invoked on the .NET component, which aborts any running task, and starts a new task which verifies whether the configuration is complete. The definition of a complete configuration is that all mandatory attributes have been assigned a value.

If the verification fails in the first attempt, the configurator will issue a new task to attempt to deduce any unassigned mandatory attributes. In the illustrated example, the configurator is not able to deduce all mandatory attributes, and so a message will be shown that informs the user that additional assignments are required. The user must then assign values to the remaining mandatory attributes. Here the user makes a new assignment and then presses the Ok button again, to complete the configuration. This time the verification passes as all mandatory attributes now have a value.

An important thing to notice is that the configurator instance is active or ‘alive’ throughout the configuration session. As you may know, the .NET configuration component uses a background thread to process the configuration model without locking the UI. In this way the configurator is always able to act on new user input.

 

 

Product Configuration Synchronous Execution

This blog post describes an new way of interacting synchronously from code with the
Constraint-Based Product Configurator which has been introduced in Microsoft
Dynamics AX 2012 R3 CU8.

 

Scenario

The scenario that drove the introduction of this feature can be described as follows:

 

An external 3rd party sales configurator outside of Microsoft Dynamics AX 2012 is used to
assign values to a subset of attributes(a partially configured order), from
which the remaining mandatory attributes can have their values deduced using
the Microsoft Dynamics AX 2012 Configurator, thereby completing the order.

 

 

Once the all the values have been deduced, assuming all values are valid, they can be passed on
to the back end configuration module, which will create the BOM and potentially
the Route (if the model has a Route).

 

Implementation

Included in Microsoft Dynamics AX 2012 R3 CU 8 is a new derived version of the PCRuntimeConfigurator class, named PCRuntimeSynchronousConfigurator.

This class is designed, as the name indicates, for synchronous interaction with the .NET
Configurator component.

 

The configure method on the class is the method
which exposes the new functionality added to the .NET Configurator to Xpp. The
method takes three arguments; the model as xml, the attribute assignments as
xml and a the number of milliseconds which can be used before a timeout occur.
The return of the method is a IsConfigurationComplete enum value, from which
result of the configuration can be determined;

 

  • Complete
    • The configuration is complete
  • Incomplete
    • One or more mandatory attributes does not have a value
  • Timeout
    • The configurator was not able to complete the configuration within the given timeout limit
  • Contradiction
    • One or more constraints have been violated

 

Note:

The PCRuntimeSynchronuosConfigurator class exposes
the functionality required by the .NET configurator component to support the
above scenario but it is not yet integrated with any order (sales, production
etc) or product variant creation nor is it integrated with the BOM and Route
generation.

 

KB Article with number 3028719 should be Applied on top of R3 CU 8 as it addresses a stability issue in the solution.

 Example

 In this example values are passed from the simulated 3rd party configurator into Dynamics AX 2012 through a web service, as illustrated below:

 

 

To expose the PCRuntimeSynchronousConfigurator class through
a web service, we start by introducing a new class
PCTechDemoService
which implements a method with the SysEntryPointAttribute code attribute, which is
needed for a method to be exposed as a web service.

 

In this simple implementation the example method looks like this:

 

[SysEntryPointAttribute(true)]

public boolean configure(PCName _modelName, str _xmlValues)

{

    boolean ret;

    str values;

 

    PCRuntimeSynchronousConfigurator configurator  = PCRuntimeSynchronousConfigurator::construct();

    PCProductConfigurationModel productConfigurationModel  =  PCProductConfigurationModel::findByName(_modelName);

    values = ‘<Assignments>’ + _xmlValues  + ‘</Assignments>’;

   
if(configurator.configure(productConfigurationModel.getXML(), values,120000) == Microsoft.Dynamics.Ax.Frameworks.Controls.ProductConfiguration.IsConfigurationComplete::Complete)

    {

        ret = true;

    }

 

    return ret;

}

Now we can create a Service in the AOT which uses the PCTechDemoService
class and its configure method as an operation. To use this service, it needs
to be put in a service group, which can then be deployed.

 

 

To test the service, navigate to System administration > Services and Application Integration Framework > Inbound ports. Here we find our new PCTechDemoServiceGroup, copy the WSDL URI value.

 

 

 

Open Visual Studio Command prompt and type:

Wcftestclient <Your WSDL URI>

 

This will open the WCF test client where we can now see our web service.

 

For the demo data set I have used, I will use the following argument values

 

_modelName : 20001

_xmlValues : <Assignment xPath=”powerCableLength” value=”10″/><Assignment xPath=”videoSystem/television/size” value=”42″ />

 

Note: the xPath mechanism used to identify the attributes in model.

 

 

If you are familiar with the 20001(Home theater system) model, you will know that it has just two
mandatory attributes which are not assigned by defaults; the powerCableLength
on the root component and the size on the television component.

 

Attached you will find an Xpp project with code used for the example.

 

Enjoy

 

 

 

Demo.zip

Product Configuration Performance : Solver strategy

This post is part of the series of posts explaining performance improvements introduced in
Constraint-Based Product Configuration in Microsoft Dynamics AX 2012 R3 CU8.

The Solver strategy concept was first introduced in Cumulative update 7 for Dynamics AX 2012 R2 and has been extended in Cumulative
update 8 for Dynamics AX 2012 R3. It now includes the following strategies:

  • Default
  • Minimal domains first
  • Top-down

What is a solver strategy?

Imagine you were given the task of solving a 100 piece jigsaw puzzle. How would you start?

A common solving strategy is to start with the edges and move towards the middle, most of us
will either have done this ourselves or if not it should be pretty simple to
convince yourself that this strategy is sound.

 

Now, what if the puzzle you have to solve does not have straight line edges (often referred to
as impossible puzzles)? Suddenly our edge-first strategy will be dramatically less efficient as the edges are much more difficult to identify.

 

For the Solver, a configuration model is a bit like a jigsaw puzzle which needs to be solved.
With the Solver strategy concept, we have enabled you to set the strategy which
the solver will use when it solves the model. Configuration models can however
be very different in nature and the strategy for solving one model efficiently
may prove to be inefficient to solve a different model.

What is the impact?

The impact of response times has been shown on real customer models, to go from minutes to
milliseconds. For this reason it is really worth your time to spend a few
seconds to change this one setting, to see if a change in Solver strategy could
have this impact on your configuration model.

You can change the Solver strategy setting in the model properties form.

Which strategy to choose

Currently there is no build in logic which automatically detects which solver strategy will be most efficient, so for now, you will have to try them out.

Default

What can be said about the different solver strategies is that the default Solver strategy has been optimized so solve models which rely on table constraints. On all the customer models we have seen which use table constraints to a large extend this
solver strategy has proved to be the most efficient.

Minimal domain first and Top-down

These two strategies are closely related. The Top-down strategy, which has been introduced with CU 8 has shown to outperform Minimal domain first in all of our studies, but for
backwards compatibility we have decided to keep the minimal domain first strategy
in the product. Both of these strategies have shown to be more efficient for
solving models which contain several arithmetic expressions and where table constraints are not used. However, there are still examples where the default solver strategy will out perform these, so remember to try each.

Product Configuration Performance : Caching

This post is part of the series of posts explaining performance improvements introduced in Constraint-Based Product Configuration in Microsoft Dynamics AX 2012 R3 CU8.

 

Motivation

The product configuration model is persisted in a normalized data model in the database. As a result of this, this tables in the data models will need to be queried in order to obtain all the needed information to load a product configuration model. The parent-child relation between components and subcomponents require that this is done in a recursive manner, thus it is not possible to retrieve all the information in a single select statement. For large models the traversal of the data model is a time consuming operation. However we are not just traversing the model, we are also constructing an XML representation of the model that is relevant for a given configuration session. If the model is not changing, all the end users are basically paying a performance penalty of having the same XML generated over and over again. This is why caching is has been introduced.

 

The setup

Runtime caching is disable by default, so you need to perform a contience decision if you would like to enable it. The parameter of enabling runtime caching is located in the Product Information management setup form.

 

 

Working with the cache

Once enabled, cached elements will be loaded with the latest cached value, if you change the value of a cached element in the model details form, be sure to clear the cache before loading the model.

 

It is not recommended to have the cache enabled during development of configuration models, because the cache will need to be cleared manually by pressing the “Clear cache” button i.e. the cache is not cleared automatically when you update the model.

 

 

 

The clearing of the cache happens on a per model basis, so even if two models are using the same components, clearing of the cache should be performed for both models independently.

 

The implementation

The runtime cache manager class is to be used for all interaction with the runtime cache. Both classes and record values can be cached see list be below for currently cached elements.

 

Current cached elements

  • Tables (records)
    • The entire model definition
  • Classes
    • RuntimeAttributeType instances used for system defined table constraints

 

Keys to the cache

  • Product configuration model record ID
  • Language ID
  • Price model record ID
  • Price model currency

 

The above elements define what is used as the identify an entry in the cache. If a request to load a configuration model does not match on all the key elements available in the cache, then the XML will have to generated for the specific request.