Thursday, 5 December 2013

Upload Images to Inventory items : Programmatically.

The below code helps to upload the images and attach them to the inventory items via the docuRef programmatically.


static void Job1(Args _args)
{
    DocuRef     docuRef;
    DocuValue   docuValue;
    InventTable inventTable;
   
    System.String[] fileNames;
    int fileCount, i;
   
    str fileName, trimmedFileName;
    BinData binData;
   
    ;
   
    binData = new BinData();
    fileNames = System.IO.Directory::GetFiles(@"C:\Images");
   
    fileCount = fileNames.get_Length();
   
    for (i=0; i<fileCount; i++)
    {
        fileName = fileNames.GetValue(i);
       
        // Get only the file name. If value returned is C:\Images\Car.jpg, get only Car.jpg
        trimmedFileName = substr(fileName, strscan(fileName, '\\', strlen(fileName), -strlen(fileName))+ 1, strlen(fileName));
       
        if (trimmedFileName)
        {
                   // Assuming file extension is always .jpg, removing it
                   trimmedFileName = strreplace(trimmedFileName, ".jpg", "");
        }
        // assuming image name matches item name in AX
        inventTable = InventTable::find(trimmedFileName);
       
        if (inventTable)
        {
            binData.loadFile(fileName);
            docuValue.File = binData.getData();
            docuValue.insert();
           
            docuRef.ValueRecId = docuValue.RecId;
            docuRef.RefTableId = tableNum(InventTable);
            docuRef.RefRecId = inventTable.RecId;
            docuRef.RefCompanyId = curext();
            docuRef.TypeId = "Image";
           
            docuRef.insert();
        }
    }
}

Cheers,
Nikhil

Tuesday, 29 October 2013

AX Performance : Cluster Index


Hello,

Cross posting the original blog, I have tried the query and it gives good results !!!

http://www.axstart.com/cluster-index/#!

Regards,
Nikhil

---------------------------------------------------------------------------------------------------------------------

These days we have the surrogate key in AX 2012. In general it is a recid Index that acts as primary and cluster index. Theoretically this looks perfect as long as we develop in the AX 2012 style. But there is a catch to it. First you may think this index can’t get fragmented. This is true only when one AOS is running; when multiple AOSs are running, they all have their recid pool; so getting the latest record should not be “order by Recid DESC” but “order by createdDatetime” DESC.


What is the most common search query on the table? In case your code uses the recid in the find method, it is OK. Personally I can’t predict the most common search query on any table, especially when code is not live for a while and upgrade or conversion code is running.
So, how to solve this riddle;

Well I found this blog post http://sqlserverplanet.com/indexes/choosing-the-best-clustered-index

It is a clever query

DECLARE @NonClusteredSeekPct float
DECLARE @ClusteredLookupFromNCPct float
SET @NonClusteredSeekPct = 1.50 -- 150%
SET @ClusteredLookupFromNCPct = .75 --75%

SELECT
    TableName                   = object_name(idx.object_id)
    ,NonUsefulClusteredIndex    = idx.NAME
    ,ShouldBeClustered          = nc.NonClusteredName
    ,Clustered_User_Seeks       = c.user_seeks
    ,NonClustered_User_Seeks    = nc.user_seeks
    ,Clustered_User_Lookups     = c.user_lookups
    ,DatabaseName               = db_name(c.database_id)
FROM sys.indexes idx
LEFT JOIN sys.dm_db_index_usage_stats c
ON idx.object_id = c.object_id
AND idx.index_id = c.index_id
JOIN (
    SELECT idx.object_id,nonclusteredname = idx.NAME,ius.user_seeks
    FROM sys.indexes idx
    JOIN sys.dm_db_index_usage_stats ius
    ON idx.object_id = ius.object_id AND idx.index_id = ius.index_id
    WHERE idx.type_desc = ‘nonclustered’ AND ius.user_seeks =
    (
        SELECT MAX(user_seeks) FROM sys.dm_db_index_usage_stats
        WHERE object_id = ius.object_id AND type_desc = ‘nonclustered’
    )
    GROUP BY idx.object_id,idx.NAME,ius.user_seeks
) nc
ON nc.object_id = idx.object_id
WHERE idx.type_desc IN (‘clustered’,'heap’)
AND nc.user_seeks > (c.user_seeks * @NonClusteredSeekPct)
AND nc.user_seeks >= (c.user_lookups * @ClusteredLookupFromNCPct)
ORDER BY TableName


 As you can see we still have a long way to go (it is default AX)

 

Friday, 11 October 2013

MS Dynamics AX 2012 : Security Framework Presentation

Hello,

Attaching below is a presentation created by me on Microsoft Dynamics AX 2012 Security Framework.

Link : http://sdrv.ms/19Esh6f




Please let me know if you find this helpful.


- Nikhil Pavagadhi

Wednesday, 2 October 2013

XSL Transformation with SOAP header: In AIF MS Dynamics AX 2009


The design approach mentioned in this blog helps to overcome the limitation of the in AIF AX 2009.

Scenario:

Working with an AIF Inbound Integration, where in the XML file has to be transformed to the AX Schema with the AIF SOAP header information embedded in the AX XML.

The AIF SOAP header is an important information for identifying the Endpoint and other Service related information.

-          3rd party XML file

-          AIF AX 2009

-          Inbound direction to AX

-          XSL transformation

-          AX XML to contain the AIF SOAP Header information

This feature by default is not supported in product MS Dynamics AX 2009.

This is addressed in AX 2012 but this has to be customized to accommodate in AX 2009.



Solution:

The above scenario can be achieved by transforming the XML file and inserting AIF SOAP header information in the adaptor classes, before it gets inserted in the AIF Queue manager.



Steps to achieve the solution:

1.       Create a check box on the AIF Channel table to identify this type of integration scenario. This checkbox will be ticked.
 

 
 
 
2.       Create a Boolean Parm method on the Adaptor class to identify this integration. You can us the standard adaptors like AifFileSystemReceiveAdapter or create your custom adaptor.
3.       Write code on the AIFReceiveInbound Processchannel method to set the parm method in the Adaptor class if the new checkbox field on the AIFChannel is ticked.
 
4.       Modify the AifFileSystemReceiveAdapter.readfile() method on the adaptor class to do the below
a.       Transform the XML. This can be done by various methods like calling the .net class XSLTransform or by using external tools in AX.
b.      Insert the required AIF header information like the <SourceEndPoint> in the XML.
 
 
Please let me know your feedback / questions.
 Cheers,
Nikhil Pavagadhi