Dynamics AX
  RSS Feed  LinkedIn  Twitter
Want to turn you're data into a true asset? Ready to break free from the report factory?
Ready to gain true insights that are action focused for truly data informed decisions?
Want to do all of this across mutliple companies, instances of Dynamics and your other investments?
Hillstar Business Intelligence is the answer then! (www.HillstarBI.com)

Hillstar Business Intelligence for Microsoft Dynamics AX and NAV on Mobile, Desktop, Tablet


Let us prove to you how we can take the complexity out of the schema and truly enable users to answer the needed questions to run your business! Visit Hillstar Business Solutions at: www.HillstarBI.com

Monday, July 31, 2006

Map & MapEnumerator Objects

Something that I find myself using a lot in code is Map and MapEnumerator objects. Back when I first started in Ax we use to store values in tempTables. This still has it's place, but it's more over head than using a Map. A Map, or several of them, can be used as a temp data store for the given scope of a process. This takes us less over head, and is much quicker than a Temp. Table.

I have used maps in different locations, but the point of a map is to store whatever values you need to, and at a given point act on those values. Below are two code examples. The first is an example of how to create a map, and insert values into it:

Map Example:

Map m;
;

m = new Map(Types::Integer,Types::Integer);

MarkMap.insert(InventTable.RecId,_markSKUs);
MarkMap.valueSet();

Below here is code for taking a known key value and lookup the corresponding value assoicated with the given key:

MarkMap.exists(InventTable.RecId)
MarkMap.lookup(InventTable.RecId)

This is a wonderful way to look up the value because you have the exact key. What if you wanted to transverse or enumrate through a given map to act on each value. This would be similar to moving through a resultset, etc:

MapEnumerator ME;
;

ME = new MapEnumerator(MarkMap);
while(ME.moveNext())
{
// .. preform some logic ..
}

With this you can now walk through or enumrate through a given map and act upon each value stored in it. Like I said, Maps are very cool, easy to use, and much faster and preferred than using a temp table. Check back soon for more posting on code examples, how to's, etc.

Find a job at: www.DynamicsAXJobs.com

Friday, July 28, 2006

using the SysDictClass to create and use objects

One of the more intersting approaches to a solution I came up with was to use the SysDictClass to create objects and run the objects methods. Basically I was creating an import tool for EDI that needed to be easily expandable and associated with other customers / vendors. So I came up with a import formating concept similar to the Check formating or VendPaym class structure.

Basically you create a Process [Action Class] and a Data [Formating] class. During the 'configuration' a user would take and select say a vendor they wanted to import Items from to re-sale. Well for that Vendor they would use a new form to select what type of Process class and action this was. So for the new item imports they would select Import Items, and then select the Process class to be used. This would then be stored in a table, and when new data came in from that vendor a Batch would kick off an overall processing class, that would take the passed in VendorId and use it to see if that Vendor has a process class associated with it. If so then it would take the string value of the class name and execute the run method of that class. From there what ever was in the run would happen, and the importing would work. below is an example of the code used to create a object from the SysDictClass and then call it's run method.

SysDictClass obj;
;

obj = new sysDictClass(ClassName2id("Process_V0001"));
obj.callObject("run",obj.makeObject());

Now with this structure in place the client could easily create a new Process class that would extend from a given base class, that all would contain a run. This run method would house the starting point for any business logic that needed to be ran, and then they would assocaite this class with the Vendor through the new table.

Next time an event fired for the given VendorId, if an entry existed, it would then return that string value of the class and the logic would be executed. This in turn makes it a very flexible / scalable approach, so that only a new process class needs to exists, and a Union between that class and the VendorId, along with a description in the table of what this does.

From here I will most likely create a Wizard that will walk through and based on answers actually create the new Process class for them. (or at least as much as it can create.) All in the name of making this flexible and easy to add more partner processes.

Find a job at: www.DynamicsAXJobs.com

Wednesday, July 26, 2006

Using C# code to connect to Ax 3.0

To continue down the path of integration with Ax 3.0, today I wanted to take the time and post some C# code that can be used in order to connect to the AxaptaCOMConnector 1.2 and use it to execute code.

The tricky thing about the COM Connector is the logon, and also when to use Null values for object values that need to be set. If you look at the VB.Net examples, you want see this. Also as part of this, I show you how to make use of the CallEx or CreateEx methods which take a ParametersList Array of values. I much prefer this, in the place of the standard call and having to use Null. In the example below though I make use of both so you can see the difference:

First the Connection code:

Using AxaptaCOMConnector;

private AxaptaCOMConnector.Axapta Ax()
{
// This method will return an Open AxaptaCOMConnector Object and allow for execution of needed
// Code.
Axapta _ax;
_ax = new Axapta();
try
{
_ax.Logon("jbg", "", "", "");
}
catch(System.Exception err)
{
System.Diagnostics.Debug.Print(err.Source);
System.Diagnostics.Debug.Print(err.StackTrace);
System.Diagnostics.Debug.Print(err.Message);
}
return _ax;
}

Now to keep things simple, the above code is ran on a box that contains the COM Connector and the Ax instance. With that in mind, the above code will return a new Axapta COM instance to be used to execute code.

Next let's use the connection we now have to execute code:

public Boolean InvokeItemIF(string VendorId,
string TableName) {

AxaptaCOMConnector.IAxaptaObject srInvokeItemIF;
AxaptaCOMConnector.AxaptaParameterList srInvokeItemParams;
Boolean result;

if (VendorId != "" && TableName != "")
{
try
{
srInvokeItemParams = new AxaptaParameterList();
srInvokeItemParams.Size = 2;
srInvokeItemParams.set_Element(1,(Object)VendorId);
srInvokeItemParams.set_Element(2,(Object)TableName);
srInvokeItemIF = AXCN.CreateObjectEx("srInvokeItem", srInvokeItemParams);
result = (Boolean)srInvokeItemIF.Call("ProcessItems2",null,null,null,null,null,null);
}
catch(System.Exception err)
{
result = false;
}
}
else
{ result = false; }

this.KillAXCN();
return result;
}

The above code here makes use of an IAxapaObject interface, and a AxaptaParameterList. With these along with our COM Connection we are able to take the passed in values of VendorId and TableName to then create a new Object which represents an Ax X++ class, that is then passed these values into the New() or constructor. From there we tell the Object to execute the ProcessItems2 method.

Here we use a Call and a CreateObjectEx. Both ways work, but I prefer to Ex because you are not limited on the amount of Params that you can pass. Once the call is completed to ProcessItems2, it returns a boolean value which we then return for this method.

Also part of this is the killAXCN() method call. This method is next:

private void KillAXCN()
{
// Close the Open AXCN connection
AXCN.Logoff();
AXCN = null;
}

Basically this method will take and destroy the COM Connection. Pretty striaght forward.

The issues that you run into when using the COM Connector is getting it to work in a production enviornment with multiple AOS(es). I always recommend having the COM Connector installed and registered on a Batch or Application server, which then has it's own configuration of AX to use, and also can host the Web Service that you use to expose access to the Ax COM Connection and code you need to execute.

Well Check back for more as I will dive deeper and deeper into this, as well as make the switch to 4.0 and talk about the differences!

Find a job at: www.DynamicsAXJobs.com

Wednesday, July 19, 2006

WINSTA.dll Error

Recently came across a strange error during batch job processing taking to long for posting packingslips, etc. Found out that this has happened before to someone else with a similar story and the fix to the solution is here:

http://www.mail-archive.com/axapta-knowledge-village@yahoogroups.com/msg07270.html

I thought this was a good thing to link to, because it's a strange one and it was not so straight forward when it came to finding the answer.

Keyword is WINSTA.dll
Message:
"This application has failed to start because WINSTA.dll was not found. Re-installing the application may fix this problem."

Hope this helps someone as it helped me!

Find a job at: www.DynamicsAXJobs.com

Integrating with Ax 3.0

Pre-Post:
I wanted to address with this post, my lack of ability to post new items for the past month. I have been swamped doing work, and admit have not had much time to post. I do however plan to get back on a twice a week schedule, hopefully within the next two weeks.


Integrating with Ax 3.0

Recently I have been doing a lot of work, taking 3.0 instances and integrating them with .Net applications, and EDI / EAI with BizTalk. This are seems to be one that does not have a lot puhlished on the net, so I thought it would be nice to have a nice post that talks about the different ways to achieve two-way integration with a Ax 3.0 instance.

The obvious is using the Business Connector (COM+) object. The business connector is a COM / COM+ object that is installed on a given box, that gives outside applications an interface into calling Ax code, and preforming Ax logic without having to be logged into an Ax Client Session.
My work with the Business Connector has mostly been with .Net / C#. Basically you register the Business Connector on a given AOS, etc. and then you can reference the AxaptaCOMConnector Object from within a given langauge. You can then create a Connector object, and create instances of object from within Ax that are used to preform logic, just as if you where in Ax.

With that said, there are some things to keep in mind about the Business Connector. For instance it's a COM / COM+ registered object, that come become unstable if not maintained correctly. Basically what I mean by that is if you are connecting and dropping the connection over and over, the over head generated from such transactions can become an issue, and I have noticed the COM connector becomes unstable or 'flaky'. The best way to manage such a thing that I have found is create a web service that wraps the objects you need or want access to, and only open the connection on the first time the Web Service is called. Then store the object in memory (cache) and use the open connection throughout all of the rest of the calls. You still have to handle the proper closing of the object, that's why you only close it when the web serivce or App is truly shuting down, and unloading from memmory.

For me, using web services as a messaging layer has been very successful. The next are to talk about inegrating with Ax is through making COM calls from within Ax itself. To give an example, so you had a custom end point in BizTalk that you wanted to interact with. How would you do it in Ax 3.0? Will the end point would be exposed as a web service, so for that matter how would you interact with Any web service from within Ax 3.0. Simple!

You create a C#.Net class that is a wrapper for the Web service that is then registered as a COM componet on the given machine. Then you can use the COM Wizard form with Ax 3.0 to create a wrapper class to call the COM object which, can in turn be used to interact with said web service. This approach can get tricky too, with say having multiple AOS(es). Basically though you just make sure the correct version of the object is registered on every AOS, and that's pretty much it for the trickiness.

That's all I have time for now on this subject, which can get really deep. For our forseen future that use of COM is going out the window which I believe is the right move. In 4.0 the Business Connector is native .Net, and calls can be made to .Net assembly in the GAC from DAX 4.0... so more stability and flexible is there for us in 4.0.

Check back soon for the next peice on this subject related to 4.0 integration!

Find a job at: www.DynamicsAXJobs.com

Friday, July 14, 2006

Create a new Datasource and link it through code!

Have you ever wanted, through code, to add a new datasource to an already existing one? Well below is some code that will show you how:

QBSInvent = QBSSum.addDataSource(TableNum(InventItemLocation),"InventItemLocation");
QBSInvent.addLink(fieldnum(InventSum,ItemId),fieldnum(InventItemLocation,ItemId));
QBSInvent.addLink(fieldnum(InventSum,inventDimId),fieldnum(InventItemLocation,inventDimId));
QBSInvent.addRange(FieldNum(InventItemLocation,WhsABC)).value(int2str(gWhsABC));

Basically in this code I create a new Query Database Source, and add it to an already existing one. Then I take and addlink methods to link the two datasources, then the range, and bang! My new datasource now works and is part of the lookup for the given query that may be running for a report, or anything. This is very useful code for working with Dialog's, etc. And you want to add ranges based on different selection types that the user makes.

Check back soon as I will post about integration with Ax 3.0 and what to look for in 4.0!

Find a job at: www.DynamicsAXJobs.com


Copyright 2005-2011, J. Brandon George - All rights Reserved