Microsoft_MVP_banner

Collection classes in AX – What, When and How to use

Data inserting, traversing and retrieving can be done with many different ways in AX. We do have different collection classes for it and each one has its own importance and performance impact. Let’s talk about each one by one and compare it. List –          are structures, contain values of any X++ type that are accessed sequentially –          all values must be of same X++ type (specified through baseEnum types) –          type is defined on creation and cannot be modified after initialization –          can be traversed through ListEnumerator class –          values can be added from both sides e.g. using addEnd() and addStart() methods  Example 1 static void ListExample1(Args _args) {     List list = new List(Types::String);    // Declare and initialize List of String type     ListEnumerator  enumerator;             // Declare ListEnumerator class to traverse list             list.addEnd(“Faisal”);                  // Add values at End of the List     list.addEnd(“Fareed”);                  // Add values at End of the List     list.addStart(“AX Developer”);          // Add values at Start of the List         enumerator = list.getEnumerator();      // initialize listEnumerator class object         while (enumerator.moveNext())     {         print enumerator.current();     }     pause;    }   Output: Traverse from left to right Example 2 Lists can be initialized from container too. static void ListExample2(Args _args) {     Container       companyRange;               // Declare container     List            list;                       // Declare List     ListEnumerator  enumerator;                 // Declare ListEnumerator class to traverse list                companyRange = [curext()];                  // initialize container with current company        // we can pass multiple values here but need to be of same             datatype as this is used in List in below code            list = con2List(companyRange);         enumerator = list.getEnumerator();          // initialize listEnumerator class object         while (enumerator.moveNext())     {         print enumerator.current();     }     pause;    } Example 3 Below code is actually an example to copy user roles from one user to another. Where I used ‘List’ to store records what roles have been moved across. static void ListExample3(Args _args) {     boolean                 ret = true;     SecurityRole            securityRole;     SecurityUserRole        securityUserRole;     SecurityUserRole        securityUserRoleExist;     SecurityUserRole        securityUserRoleInsert;     OMUserRoleOrganization  userRoleOrganization, userRoleOrganization_Insert;     List                    copiedUserRoles = new List(Types::String);     ListEnumerator          lEnumerator;        try     {                while select securityUserRole                 where securityUserRole.User == fromUser             notExists join * from securityUserRoleExist                 where securityUserRoleExist.SecurityRole    == securityUserRole.SecurityRole                     && securityUserRoleExist.User           == toUser         {             select securityRole where securityRole.RecId == securityUserRole.SecurityRole;             copiedUserRoles.addStart(securityRole.Name);             securityUserRoleInsert.initValue();             securityUserRoleInsert.SecurityRole = securityUserRole.SecurityRole;             securityUserRoleInsert.User         = toUser;             securityUserRoleInsert.insert();             securityUserRoleInsert.clear();             while select userRoleOrganization                     where userRoleOrganization.User == fromUser                         && userRoleOrganization.SecurityRole == securityUserRole.SecurityRole             {                 userRoleOrganization_Insert.initValue();                 userRoleOrganization_Insert.OMHierarchyType             = userRoleOrganization.OMHierarchyType;                 userRoleOrganization_Insert.OMInternalOrganization      = userRoleOrganization.OMInternalOrganization;                 userRoleOrganization_Insert.SecurityRole                = userRoleOrganization.SecurityRole;                 userRoleOrganization_Insert.SecurityRoleAssignmentRule  = userRoleOrganization.SecurityRoleAssignmentRule;                 userRoleOrganization_Insert.User                        = toUser;                 userRoleOrganization_Insert.insert();                 userRoleOrganization_Insert.clear();             }         }     }     catch     {         ret = false;     }     if (ret)     {         lEnumerator = copiedUserRoles.getEnumerator();         if (copiedUserRoles.empty())             info(strFmt(“User %1 and %2 already have the same user role”,fromUser, toUser));         while (lEnumerator.moveNext())         {             info(strFmt(‘%1’,lEnumerator.current()));         }     }     else         error(strFmt(“Aborted please review error list above”)); } You can also have a look on this post to find difference between Iterators and Enumerators.                      Maps –          can be used as a temp data store for the given scope of a process –          are much quicker than temp tables –          allows you to associate one value (the key) with another value –          values can be any valid X++ type static void mapExample1(Args _args) {     Map             mapExample;     MapEnumerator   mapEnumeratorExample;     CustTable       custTable;         mapExample = new Map(Types::String,Types::String);         select custTable where custTable.AccountNum == “144212”;         mapExample.insert(CustTable.AccountNum, CustTable.name());         mapEnumeratorExample = new MapEnumerator(mapExample);         while (mapEnumeratorExample.moveNext())     {         if (!mapExample.empty())         {                        print mapExample.lookup(custTable.AccountNum);         }            }     pause; } Good information about Maps is also shared here Containers MSDN page describes it very best http://msdn.microsoft.com/en-us/library/aa874816.aspx Containers can be used to get multiple values returned from any method. Original method private container getActualAmount() {     Container   amountContainer;     container   textContainer;        ;     for()     {                amountContainer = conIns(amountContainer);         textContainer   = conIns(textContainer);            }     return [amountContainer, textContainer]; } Called From container   AmountsC = conNull(); container   TextC    = conNull(); [AmountsC, TextC]   = this.getActualAmount(); Set values to use for your logic ExampleTable.Field1 = conPeek(AmountsC,1); ExampleTable.Field2 = conPeek(AmountsC,2); Important points about Containers They are value based structure. So no class based object stored on it. They are similar to linked list or array like structured. Their size fixed at time of declaration. When you insert update or delete any value from container, a new container is created. They always copied by value. Containers are base 1 not like array based zero.

FaisalFareed@2025. All rights reserved

Design by T3chDesigns