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

Wednesday, January 18, 2012

AX 2012 - Using Financial Dimensions when Creating Products





I hope everyone is having a great week so far, and your knee deep into your Dynamics AX projects. I wanted to take a little time this morning, and post a bit about the use of Financial Dimensions when creating products in AX 2012.

I covered the creation of products, using the EcoResProductService, in the following post: Microsoft Dynamics AX 2012 - A Dive into Services, Consuming Document Services



What I did not cover in this post, is around the filling of the DefaultDimension field, from the InventTable object, during the Releasing of a Product to a legal entity, via the InventItemService. Since the time of that posting, I've had a chance to work with this further, and wanted to share, how you would go about, still using these document services, to assign the Default Dimension for a Released Product.



With the understanding we have from the previous post, we need to know understand our starting point for being able to set the Default Dimension value, for a released product. There is a set of classes, that are apart of the AIF class framework within AX 2012, that enable us to build up the default dimension for a specific released products. These are: AifDimensionAttributeValueSet & AifDimensionAttributeValue.

Also as part of this Dimension value set creation process, there is a need to work with the AfStronglyTypedDataContainerList, which is a container for the AifDimensionAttributeValue objects we build up for setting our product dimension values.

So since this is our starting point, we would need to define these, in the header section of whatever method or job is performing the action of releasing creating products. We would then, have something that looked like the following code.:


// DefaultDimension variables:
AifDimensionAttributeValueSet DefaultDimSet;
AifDimensionAttributeValue dimensionAttributeValue;
AfStronglyTypedDataContainerList dimensionAttributeValues;


With this, we know have the variables needed, in which we can use, along with the InventItemService for setting our Default Dimensions. Moving forward then, within this concept, and assuming you've already got the code from the previous post, lets work with these objects and see the process of creating our Default Dimensions.



// Set DefaultDimension data
dimensionAttributeValues = new
AfStronglyTypedDataContainerList(#AifDimensionAttributeValue);

dimensionAttributeValue = dimensionAttributeValues.addNew();
dimensionAttributeValue.parmName("Department");
dimensionAttributeValue.parmValue("SomeValue");

dimensionAttributeValue = dimensionAttributeValues.addNew();
dimensionAttributeValue.parmName("Purpose");
dimensionAttributeValue.parmValue("SomeValue");

dimensionAttributeValue = dimensionAttributeValues.addNew();
dimensionAttributeValue.parmName("CostCenter");
dimensionAttributeValue.parmValue("SomeValue");

invTbl.createDefaultDimension().parmValues(dimensionAttributeValues);


With the above code example, we can see that via the InvTable variable, which represents an InventItem_InventTable object, we can create our DefaultDimensions, as well as fill in the Financial dimension name as well as value. In doing this, we are now able to set default financial dimensions correctly, for products we are releasing to a specific legal entity.

To help with this topic further, Becky Newell, a super star support engineer for Microsoft, gave us an early Christmas Present this past Dec., in which she gives us code example of working with Financial dimensions, for Journal Entries. You can find that post, at the following: Creating General Journals in AX 2012 in X++.

Well thats all I have time for this post, I hope this helps you out, and futher shows the powerfully simple nature of AX 2012, and the ability to work with the infinitely possible financial dimensions that can exists. Till Next time!



Visit Hillstar Business Intelligence (www.HillstarBI.com) in order to truly unlock your data trapped in your Microsoft Dynamics investment. With our value driven business intelligence strategy Hillstar help you transform into a data informed company.


Follow Me @:
RSS Feed  LinkedIn  Twitter

"Visit the Dynamics AX Community Page today!"

Labels: , , , , , , , , , ,

Tuesday, March 30, 2010

Dynamics AX Threads - More details

Recently, I wrote a post about making use of Threads in X++ development, for Dynamics AX. A direct link to that post can be found here.:
Dynamics AX 2009 - X++ Thread Development

In the above post, I went over the Thread class, as an intro really, showing how to create a method that would be executed from a spwaned thread, and a job that kicks such a thread off for working with Sales Order data.

Again, the idea with that post was to really show what Threads can do, get you thinking about threads, and also some limits I ran into, with trying to spawn multi level threads, within threads.

With this post, I wanted to give a little more information about working with threads, covering thread statuses and also the worker process users that show up in the online users form.

So, if you create a new instance of the Thread class, you will notice a method called, Thread.Status(). This method returns an int based value. There is really no documentation on what these values mean, so I dug a little deeper into this.

In doing so I found out the following values, as returned from a call to Thread.Status().:

  • 0 = Thread never ran

  • 1 = Thread is executing

  • 2 = Thread has finished executing



Now why would understanding these thread status values be important? Well with thread development, you have to have code that acts as the thread manager. In most cases, when your doing thread development, you are spawning more than one thread at a time. This means you need to know, for your given section of code, when all the spawned threads are finished.

Once you know all your spawned threads are completed, then you can move on in your host code, to continue and finish out whatever process is taking place.

So with the Thread Status value, you can make use of say an Array or a Map object to store the referenced spawned threads, and use that in RAM object to manage the threads, until they are all completed.

Now having multiple threads spawned, brings me to the next area I wanted to cover in this post, which is the 'Worker Process' type users you might see in the online users form.

If you notice these, possibly one per thread spawned, you will see that it seems to act like a license is being used. However, look at the active users total on the online users form and you will note the number of active users does not increase, when a worker process user is listed.

This is good news, as it would seem worker process user types, do not take up a license.

You still need to be careful and control the amount of spawned threads, as you could spawn way to many for the system to really handle. Depending on the load and actual work be performed by the Threads.

One other note about the worker process, is you will see these when you spawn the threads from a client session. Even though the thread is executing a server side static method. However if the given host code / business logic, that does the thread spawning is executed in Batch mode for example. You will not see the worker processes appear in the online users form.

So with this, we have a little better knowldge about Threads, thread status, it use with thread management, and understanding of the worker process user type.

That's all for now, but I have more post coming, so check back soon!




"Visit the Dynamics AX Community Page today!"


Labels: , , , ,

Thursday, March 11, 2010

Dynamics AX 2009 - X++ Thread Development

One of the possible technical tools that exists when developing solutions in Dynamics AX, and inside X++ is Threads. This is actually not a new thing, thread based development has been around for a while.

The whole idea of creating a seperate thread to perform a process is an accepted technique to achieve multi processes at a given time, managed from the given, seperate application thread that the user application is taking up.

With, however Dynamics AX, sometimes it's not that clear of where and why you would use Thread to achieve a given process, or development goal.

I used and use threads a lot in C#, and the Thread development that exists in C# is for robust, and can become complex. And lets face it, Thread development and management of spawned threads from a application can become complex.

So with X++, there does exists the ability to use Threads for development needs. The following is a simple example of a Thread, a Method that the Thread is executed upon, and how to execute the simple thread.





With this we see a simple threaded development approach that can be used in X++. To break this down a little bit, you have a job, class, method etc. that is performing some work. In that is wants to spawn a thread.

The method that will be spawned as a new Thread, must accept a Thread as it's only parameter, and best practice on this says it should be a server static method that is the executed thread method.

You notice that there are input parameters and output parameters. These are containers, and therefore can store a number of different in and out parameters, to and from the threaded method. This is very useful as the thread could be developed in a way that would return some output.

Now this is great and all, but when would this be used?

Since Dynamics AX is an ERP product, that means a lot of process and needed development flows have to take place in a linear approach. However there are some things that do not have to be. Or some process that can be developed, so that threads can be used to improve the performance of a long running process for example.

So, with thinking about Threads, you have to think about divison of a given process into several Threads. Thats the nature of thread development.

This means, that if a given data process is taking hours and hours, can it be devided into smaller chunks of data? If so, but you need the whole thing to process, then a Threaded development approach can be done, where the given data process can be selected, and by the division, say a date or a group, can be used to spawn a thread to import data, doe that given divison unit.

This means, that if you have, say, 100,000 records to import. And that process is taking 3 hours. But you realize, you can break these 100,000 records into 10,000 records a peice, by a Item group.

Then you can take and have a method that loops through the grouped, by Item group, selection, and spawn a thread per 10,000 or by Item Group, and therefore speed up the process x10 fold. This means that the process that was taking 3 hours, can be done in an estimated 18 mins.

This directly ties to what DAXGuy, posted about here.: DAXGuy: SSIS for Bulk insert into Dynamics AX 2009 and this represents another way of inserting a large amount of data. What this approach, using threads, offers is it's X++ based, and therefore X++ busienss logic that might live on a given table in AX can be accessed and used. Note: Thread imports, most likely will not be as fast as a bulk insert process. But when a bulk insert is not possible, think about threaded development.

Now some notes about threaded development now. One, make sure everything that a thread accesses and executes is server tier code, or server context code. This makes sense, the thread executes on the Server tier, and in doing so, can't access client side code. If you try to do so, the thread will error out.

Also, if a thread is actually executed at the Client level, even though it's server side code being executed, for every thread spwaned a worker type user license will be used, and seen in the online users form.

Also, finally, I would like to point out that Microsoft itself uses threads in the MRP process, and other processes like ReqTrans, to try and speed up the processes in these areas. Thread development should be a serious consideration, but there are some limits.

For examples I tried to do a multi-tree thread approach. Meaning I tried to spawn sets of threads in threads. This is not possible. For whatever reason, the first thread in the threaded, thread approach will execute, after that the other spwaned threads are stopped.



If the multi-tree thread approach would work, then you could spawn mutli level threads, really attacking long running processes, by breaking it up into smaller, and smaller chunks. However, as my test have shown, this is not possible.

I hope this helps shed some light on threads in Dynamics AX 2009, and that it helps getting you thinking about how threads can be used in x++ to help with your coding needs.

That's all for now but check back soon!




"Visit the Dynamics AX Community Page today!"


Labels: , , , , , , ,

Monday, February 15, 2010

Dynamics AX 2009 - Service Reference to Custom WCF Service

Alright, so making use of Service References in Dynamics AX 2009 has been out for a little while. In the past I have done post talking about white papers, and how-to's. Talking about the design of such services.

Well I wanted to take a little time and spend a little bit with creating custom WCF services, and then consuming those services within Dynamics AX.

This is not the first such tutorial on the web. There was some earlier one's done when Dynamics AX 2009 first came out. What I want to address however is details for creating a simple service, in general terms. Talk about the different aspects of these general concepts. Then in later post move through wht WCF services, over other options, and also common issues found when scaling services, promoting to other instances like production, etc.

So first lets look at a custom WCF Service. The following is such a service.

1.) A DataContract.:


2.) A ServiceContract, Defined in an Interface


3.) The underlying class that implements the given ServiceContract Interface and it's underlying OperationContract's


And


So the above show's a TestBed namespace, that includes a Class with an interface. That interface is what defines the ServiceContract and underlying OperationContracts. These are used to define what endpoints exists for consumption by a WCF client.

The DataContract, FooData, is used to define a complex (though simple example) user defined type, with properties that exist to describe what a FooData object is.

Once these are defined, I recommend actually first testing by consuming in .Net. Maybe through a Console app or .Net Windows Form. This will help to get rid of any security issues that might exists for IIS, etc.

Once this is tested, now we can move forward with consuming this within Dynamics AX.
Simply create a new project, add a new group for references, right click, add new Service reference, point to the URL where the FooSvc.svc is being hosted, and AX will create a client, used by the AOS to interact and consume this WCF custom service.

Once that is done, then you can do something similar to the following X++ code, that calls, interact, and works with the WCF Service, Operations and DataContract.:


Now lets disect some of this, and look into the details. So before this WCF Service could be consumed, it had to be created, and then published to a place where AX could consume it.

Since the idea it to talk in general terms, the Foo code concept was used, in order to be general.

So this Foo based C# .Net 3.5 code example shows a simple example of a Foo Class, that has an interface. It's important to understand that this is very similar to typical interfaces for classes. It governs how outside clients, consumers and code can interact with the class and create instances of it.

What different about this interface is the meta tag information, used by the WCF hosting .Net code to define what the given interface, and methods are. That is a ServiceContract, and OperationContract's. Or what's also know as endpoints.

These endpoints, are what AX consumes and works with. As you can see in the X++ code, .GetFooDataList(5); and .GetFooString(fooData);.

The actual code that does operate on the calls, and parameters variables sent in, lives in the public class Foo : IFoo {...}. The IFoo is familiar to anyone that has worked with C# code before.

Now to generate this interface, and class approach, simply add a new WCF Service and the wizard creates a shell for you.

Lets move forward, a look at the DataContract. Now this is different than what we have seen before in working with straight .Net Code, and .Net code through Dynamics AX, X++.

This is used to define a complex custom type, that can be passed between the WCF service code, and a consuming client. This includes Dynamics AX.

Now note, that the DataContract, FooData, is made up of simple data types, for it's DataMembers. However with this defined, and once a service reference is made from within AX, then the give FooData DataContract class, can now be passed back and forth between Dynamics AX X++ and C#.

You can see in the X++ example, that once I get the FooData based List, that I can call a method from WCF C# service, and send it a .Net object defined in that service as FooData. This can be filled with information, passed in and then operated on within the WCF service. The return, note is a simple return.

Let's also take a step back here, and look at how I get my FooData object. I am working with what appears to be an Array of FooData[]. And what I am working with is actually a List. You can see the return type for .GetDataList(5); method call.

Notice how I create an instace of the System.Collections.IEnumerator, and use that to Enumerate through the List of FooData objects.

I think it's very important to understand that you can work with List's, and specific Genrics based list that define a List with specific types that are contained within.

It's actually a pain point, if your not familiar with working with Arrays and List with WCF in general, and much less with WCF Services consumed with Dynamics AX. So this is a very good example of proven code that works for working with List of not just simple strings, etc. but actual custom complex types.

So what we have here is some basic concepts of a simple WCF C# service, that has a few OperationContracts, for our Foo.svc ServiceContract. It also has a custom DataContract used in both the X++ and C# code. And this complex type can be sent between the two.

Now one could take this simple example, and really make use of it for creating needing code in a WCF service layer. Maybe for working with other LOB, line of business, applications. Maybe for working with legacy code, or objects, or an enterprise sevice bus, with middleware message needs.

What I do want to point out, is there are certain Dynamics AX Service Reference settings, gotchas, watch outs, etc. Espically when you move from Dev to Production. Or if you need to change the WCF service and regenerate the reference inside Dynamics AX.

I plan on going over those details a little later, and taking this post further into real world solutions.

I hope this gets you thinking though about WCF services, and the power of WCF Services. As i mentioned at the start of this post, I plan on covering WCF Services vs. Web Services and why choose WCF services. Also in that next post I will cover the gotchas and watch outs I mentioned above.

See you next time!

P.S. In the meantime if you have specific questions, issues, something you would like to see with this, please leave me a comment or shoot me an email.




"Visit the Dynamics AX Community Page today!"


Labels: , , , , , , , ,

Tuesday, July 07, 2009

Calling a Custom Dynamics AX 2009 SSRS report and passing parameters - From X++

Recently, I have been doing post about making use of Custom SSRS reports with Dynamics AX 2009.

The most recent post, was the following.: Dynamics AX 2009 - Reporting Possibilites

In that post there was a comment left by someone talking about some of the limits that still exist with the custom SSRS reports.

As I point out there are pro's and con's with the custom SSRS reports for Dynamics AX 2009, however one of the things the reader pointed out was passing parameters to the custom SSRS report.

So I thought it would be worth while to do a post on exactly how to do this.

In this example I have created a custom SSRS report for Dynamics AX 2009 instance.



In this you will see I have a Query, that was used for my report, and also a report library I created using Visual Studio 2008 Dynamics AX 2009 Reporting template.

The query, has a Range of SalesId, and in doing that, this was auto added to the report parameters, in the VS2008 projects. (see below image)



This is the name of the parameter in the report def., and therefore important to note for our exercise.

So the task was to take and pass values to reports from X++. I took and create a job that does exactly that. It takes and call my custom reports, output menu item, and pass it a value for the SalesId parameter. The code follows.:


MenuFunction CustRptMI;
Args Args;
;

CustRptMI = new MenuFunction(menuItemOutputStr(srsCustomRpt),MenuItemType::Output)
Args = new Args();
Args.parm("qryCustomSSRS_SalesId=*SO-100004*");
CustRptMI.run(Args);
CustRptMI.wait();


Notice the name of the parameter is exactly the name it is in the VS2008 project for the report def. 'qryCustomSSRS_SalesId'. Then simply and = and then . You can add multiple parameters here with commas, and there you have the report being called, ran, and from X++, parameters being passed and the report generated. (See image below)



So as you can see, you can make use of X++ to call custom SSRS reports, pass in paramaters, and do this pretty simply. You just have to know the exactly parameters names, and you can go from there.

Check back soon, as more post are coming!




"Visit the Dynamics AX Community Page today!"


Labels: , , , , ,

Friday, May 23, 2008

Calling an Excel Macro from X++

All, recently I needed to know how to call an Excel Macro from X++. This is not something that is widely published anywhere on the web, and something I had to figure out.

It's actually not that hard, and the best help was looking at how I had done it before in .Net.

So here is the code example:


SysExcelApplication ExcelApp;
SysExcelWorkbooks WorkBooks;
SysExcelWorkbook WorkBook;
SysExcelWorksheet Worksheet;
;


ExcelApp = SysExcelApplication::construct();
ExcelApp.displayAlerts(true);
ExcelApp.visible(true);

ExcelApp.workbooks().open("SomeExcelFile.xls");

Workbook = ExcelApp.workbooks().item(1);
Worksheet = Workbook.worksheets().itemFromName("WorkSheetName");

ExcelApp.comObject().Run("SomeMacro"); // The Call to run a Macro


Of course there is a lot more you can do, but basically any Excel based class has a .comObject() at which you can further extend and make Excel Interop COM calls via, that go beyond what is coded for in the SysExcel Class framework.

Check back soon!

"Visit the Dynamics AX Community Page today!"


Labels: , , , , , ,

Wednesday, December 12, 2007

SysDictClass and some CAS

I ran into an issue when working with the SysDictClass. I am using this to do some 'smart' coding and make use of reflection, in order to speed up my development and not have to manually write code over and over again for the same type of thing. In doing so, I found out that this is considered a protected API now in DAX 4.0, and so you need to make use of an 'ExecutePermission' CAS Permission object, and assert that level of permission.

The error message looked similar to this:

"Request for the permission of type 'ExecutePermission' failed.
(S)\Classes\ExecutePermission\demand
(S)\Classes\DictClass\callObject
..."


So if you see this type of error, then make sure you perform an ExecutePermission Object. assert() before the code, and revert that assertion after the code block. In doing so, you will have gotten rid of this little issue.

This is the first time I had to make use of this code in a while, and so first time I ran into this being a protected API. I hope this helps someone out, as I did not find anything on the web, when searching.

Check back soon!


Find a job at: www.DynamicsAXJobs.com

Labels: , , , , , , ,


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