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.
- - 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;
}
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"));
}
- - 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
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.
Comments
Post a Comment
I will appreciate your comments !