Tuesday, 31 May 2016

Using the Dynamics AX Collection Classes

Using the Dynamics AX Collection Classes

The Microsoft Dynamics AX collection classes provide simple data structure implementation to allow developers to store and access simple types such as strings and integers, but also more complex types such as records and objects. Note that these classes are not abstract tools but used throughout base DAX code, especially areas of complex functionality including inventory closing, indirect cost calculation, production variance, master planning, and BOMcalculation.
The classes have a consistent API for creation, addition of elements, and access of elements. Each class has different restrictions on the kinds of data that can be stored and how that data is accessed. The table below summarizes these differences.
ClassDescriptionData typesAccess
ListValues stored sequentially with ability to add values at the beginning or end of the listAll values must be the same data typeUse ListIterator orListEnumerator
SetValues stored non-sequentially. Duplicates are not added to the set.All values must be the same data typeUse SetIterator orSetEnumerator
MapValues stored by using a unique key.The keys must be the same data type. The values for each key must also be the same data type.Use MapIterator orMapEnumerator
StructValues stored by using a unique string as a keyThe key must be a string. The values can be of any type.Provide the string key to the value method

While one can forego using the collection classes and rely on containers or temp tables, the collection classes are arguably a better choice in many cases. The collection classes have a richer, consistent, and less error-prone interface than containers. Collection classes can accomplish much of the same data storage and access as temp tables without having to define a temporary table in the AOT. The following sections detail the collection classes except for the Array class.

List

A list stores objects of all the same type in a sequential order. The elements can be any type specified in the Types base enum. Elements may be added to the beginning or end of the list. A summary of useful methods is shown in the table below:
addEnd(_item)Adds _item to the end of the list
addStart(_item)Adds _item to the beginning of the list
appendList(_list)Adds elements _list to the end of current list
elementsReturns the number of items in the list
getEnumeratorReturns an enumerator for traversing the list

The example code below shows creating two different lists, combining, and traversing.
public void listExample() {
    List listOne;
    List listTwo;
    List combinedList;
    ListEnumerator listEnumerator;
    SalesTable salesTable;

    // Initialize using Types enum
    listOne = new List(Types::String);

    // Initialize using extendedTypeId2Type which does not require
    // knowing the base type
    listTwo = new List(extendedTypeId2Type(extendedTypeNum(SalesId)));

    // Add a and b to list such that order is b,a
    listOne.addEnd("a");
    listOne.addStart("b");

    // Add an actual sales id and dummy sales id
    select firstOnly SalesId from salesTable;
    listTwo.addEnd(SalesTable.SalesId);
    listTwo.addEnd("Dummy_Sales_Id_12345");

    // Print first list
    listEnumerator = listOne.getEnumerator();
    info("List one");
    while (listEnumerator.moveNext()) {
        info(listEnumerator.current());
    }

    // Create a new list by combining lists
    combinedList = List::merge(listTwo, listOne);

    // Print combined list
    info("Combined");
    listEnumerator = combinedList.getEnumerator();
    while (listEnumerator.moveNext()) {
        info(listEnumerator.current());
    }
}
Below is the output produced by the above code:
image001

Set

A set is an unordered collection that contains elements of all the same type and is similar to a mathematical set in that each element must be unique. Again, the types are all the possible types of the Types base enum. Repeated inserts of a value that is already in the set will have no effect. There will be no record of how many such inserts of a duplicate value occurred. For example, if a set of Types::Integer contains only the integer 2, repeated calls to the add method with 2 as a parameter will have no effect. No matter how many such calls are made, the set will still only contain the integer 2. One possible use of a set is to store RecIds to ignore any duplicate records and insure a process only acts once per record.
Unlike a list, an element can be removed from a set directly without using an iterator. There are also powerful methods that mimic mathematical set operations that allow creation of new sets based on two existing methods. A summary of useful methods is shown in the table below:
add(_item)Adds _item to the set
delete(_item)Removes the passed in item to the set
elementsReturns the number of items in the set
getEnumeratorReturns an enumerator for traversing the set
in(_item)Returns true if _item is present in the set
difference(_set1, _set2)Returns items that are in _set1 but are not in _set2
intersection(_set1, _set2)Returns a new set that contains only elements present in both _set1 and _set2
union(_set1, _set2)Returns a new set that contains all the elements of _set1 and _set2.

The diagram below illustrates the results of set based operations which are equivalent to the mathematical operations.
image002
The code below shows an example of creating, filling, and traversing sets:
public void setExample() {
    Set setOne;
    Set setTwo;

    // Inner method for printing sets
    void printSet(Set _set, str _prefix) {
        int i;
        SetEnumerator setEnumerator;
        str output = _prefix;

        setEnumerator = _set.getEnumerator();

        // Add each element to output string 
        while (setEnumerator.moveNext()) {
            output += strfmt(" %1", setEnumerator.current());
        }
        info(output);
    }

    // Declare sets
    setOne = new Set(Types::String);
    setTwo = new Set(Types::String);

    // Fill sets
    setOne.add("A");
    setOne.add("B");
    setTwo.add("B");
    setTwo.add("C");

    // Size of set
    info(strfmt("Size of set one: %1", setOne.elements()));

    // Print sets and the results of set operations
    printSet(setOne, "Set 1");
    printSet(setTwo, "Set 2");
    printSet(Set::difference(setOne, setTwo), "Difference ");
    printSet(Set::intersection(setOne, setTwo), "Intersection ");
    printSet(Set::union(setOne, setTwo), "Union");
}
The output of the above code is:
image003

Map

A map stores key-value pairs. For each key, there is a corresponding value. Accessing the corresponding value of a key is a fast operation. The keys are unique and are all of the same type. The values do not have to be unique and also are all the same type. As with the other collection classes, the possible types are those specified by the Types base enum. Note that the key types and value types do not need to be the same and typically are not.
Some examples of maps are keys that are RecIds or strings that correspond to a numeric value. Another example is mapping RecIds from one table to a Record of another table, thus quickly and easily creating a fast performing link between two tables without having to use a temp table. The diagram below shows a map with Int64 keys mapping to reals.
image004
Useful map methods are summarized in the table below:
delete(_key)Deletes _key (and thereby its corresponding value) from the map
elementsReturns the number of key-value pairs in the map.
exists(_key)Returns true if _key is present in the map.
insert(_key, _value)Inserts the key value pair with a key of _key and a corresponding value of _value. In other words, lookups for _key will return _value.If _key already existed in the map, the corresponding value of that key is overwritten such that the new mapped value is _value.
lookup(_key)Returns the corresponding value of _key.

One important note is that calling the lookup method for a key that does not exist in the map will cause a runtime error. Therefore, the exists method should always be called first to verify that the key exists.
The MapEnumerator class traverses a map. The key and value are retrieved from the enumerator using thecurrentKey and currentValue methods.
The code below shows examples of several of the map methods including using an enumerator:
public void mapExample() {
    Map theMap;
    MapEnumerator mapEnumerator;
    real value;

    // Declare map
    theMap = new Map(Types::String, Types::Real);

    // Insert values into the map
    theMap.insert("LOT-01", 42.5);
    theMap.insert("LOT-02", 58.3);

    // Insert new value for LOT-01.  Previous value overwritten.
    theMap.insert("LOT-01", 99.9);

    // Traverse the map
    mapEnumerator = theMap.getEnumerator();
    while (mapEnumerator.moveNext()) {
        info(strfmt("key %1 value %2",
            mapEnumerator.currentKey(),
            mapEnumerator.currentValue()));
    }

    // Check if key exists
    info(strfmt("Does LOT-01 exist? %1", theMap.exists("LOT-01")));

    info("Checking if LOT-03 exists");
    if (theMap.exists("LOT-03")) {
        // Will not execute this code, so there is no error
        value = theMap.lookup("LOT-03");
    }

    // Will cause run time error: Lookup a key that is not in the map without 
    // first calling exists
    value = theMap.lookup("LOT-03");

    value = 1;
}
The code above produces the following output:
image005

Struct

struct groups information into a single entity. Any of the types of the Types enum can be stored which includes containers, dates, Int64’s, integers, objects, real numbers, records, strings, times, and UTCDateTimes. The diagram of the struct named “custInfo” shows an example struct that collects a string, real number, record, and object into a single entity.
Capture
The struct class is one of the simplest collection classes. Using a struct is similar to using a container that has a small number of values at fixed positions (such as the TradeTotals class). One major difference is that a struct is a class while a container is a built-in data type. A struct uses string indexes whereas a container uses numeric indexes. One of the problems with both is that the indexes or keys need to be managed entirely by the developer. For example, in the struct illustrated above, the value “43.58” needs to be accessed by providing the string “invoiced” exactly. Using the string “invoice” will cause a run time error because no value exists for the key “invoice”. For both structs and containers, one way to manage this issue is to access the keys/indexes using #define or methods.
The code below uses a constant for the invoiced but not the other keys. The code shows how to create and fill the struct illustrated above as well as how to iterate through a struct.
public void structExample() {#
    define.invoiced('invoiced')

    Struct theStruct;
    SalesTable salesTable;
    int i;

    // Create struct
    theStruct = new Struct(
        Types::String, "name",
        Types::Real, #invoiced,
        Types::Record, "order");

    // Fill struct
    theStruct.value("name", "John Smith");
    theStruct.value(#invoiced, 43.58);
    select firstOnly salesTable;
    theStruct.value("order", salesTable);

    // Add a new entry into the struct
    theStruct.add("orderType", SalesTableType::construct(theStruct.value("order")));

    // Print struct information
    info(strFmt("Definition string: %1", theStruct.definitionString()));
    for (i = 1; i <= theStruct.fields(); i++) {
        info(strFmt("Field name: %1 Type: %2",
            theStruct.fieldType(i),
            theStruct.fieldName(i)));
    }

    // Using exists for a key
    info(strFmt("Exists for key 'xyz'? %1", theStruct.exists("xyz")));
}
Below is the output produced by the above code:
image007
The sections below outline aspects of collection classes that may apply to more than one collection class.

Iterators vs. Enumerators

Enumerators should always be used to traverse a list, set, or map unless elements need to be deleted. Iterators can fail if they are used on a different tier than the tier where they were created. For example, code will fail if an iterator was created on the client side, but then runs on the server side or vice versa. Also, loop maintenance is easier when using an enumerator since there is no need to advance the iterator as a separate step.
while(iterator.more())     while (enumerator.moveNext())
{                          {
 iterator.next();   }
}
If the client/server problem can be safely avoided, then iterators can be used for deletion. However, there are alternative solutions (potentially expensive) to deleting elements from a collection without using an iterator. For a set, one possibility is putting elements to delete in a second set during traversal and calling the static intersection method. For a map, one could put keys to be deleted in a set, then traverse the set, deleting each key individually.

Pack and Create

All the collection classes mentioned above can be packed into a container using the pack method. A new instance of these classes can then be created using the appropriate static create method.
public void packCreateExample() {
    List aList = new List(Types::Real);
    List aNewList;
    container c;

    // Fill list
    aList.addEnd(1.61803);
    aList.addEnd(3.14159);

    // Pack the list into a container
    c = aList.pack();

    // Create a new list from the packed list
    aNewList = List::create(c);
}

Uniqueness of Tables and Classes

Special care should be taken if tables or classes need to be unique within the collection classes. This includes elements in a set or keys of a map. If you use a table as a unique key to a map, it seems that RecId is not the field used to determine uniqueness. Instead, non-system fields are checked. One way to bypass this is to add a GUID field to the table (thanks to Justin Wong for pointing this out). For classes it seems that even if two objects have the same values for variables, the objects will be determined to be unique by the collection classes.

Sorting Behavior of Sets and Maps

No matter what order elements are added to a set or keys are added to a map, when using an enumerator to traverse the set or map, the elements are in a sorted order (for string and numeric types). However, the MSDN documentation for the set class states that elements are stored in a set “in a way that facilitates efficient lookup of the elements.” It might not be safe, therefore, to rely on this sorting behavior as it might possibly change in the future.
The code below shows the sorting behavior in a set of reals:
public void setSortingExample() {
    Set set = new Set(Types::Real);
    SetEnumerator setEnumerator;

    set.add(2.3);
    set.add(3.8);
    set.add(1.2);

    setEnumerator = set.getEnumerator();
    while (setEnumerator.moveNext()) {
        info(setEnumerator.current());
    }
}
The result of this code is shown below:
image008

Resources

Information for this post was gathered from several places including:

Thursday, 26 May 2016

AOT Maps in Microsoft Dynamics AX 2012

AOT Maps in Microsoft Dynamics AX 2012

Maps are basically use to wrap the tables on run time.Some times there are some cases in which the structure of two or more tables is same with difference in their field names.In these kind of cases the field.

The fields of the maps are basically use to map fields of one or more tables.By the help of a maps we can access the fields of one or more tables with different names.

Steps of Creating the Maps:

For showing the implementation of table maps I have just created the two tables.As you can see them  in the below image.

































After that I will create the map on which I will map the fields of the above tables.

Just go to the Data Dictionary -> Maps right click and than select new map.





















Now add fields to this map.As you can see them in the below image.


















Now right click the mapping node and than select the new mapping and than set the name of the table on which you want to map.

As you can see this in the below image.













Now right click the fields inside that mapping and then set them to the fields of the table on which you are mapping.As you can see this in the below image.










Now I have created a job on which I will map a table on this map and than use it.

You can see that job in the below image.












In the above table I have map the studentA table to our map i,e studentcourse at run time and than I have set the fields of that map and than insert them.As you already know that in the above code the studentA table is already mapped to our map that is why after the insert call the data will insert into the studentA table.

My the help of Maps you can perform any operation you want as you do on table.

This was all related to the AOT Maps.

Below are some useful links related to AOT maps.

http://ajstudi0.blogspot.com/2012/10/microsoft-dynamics-ax-maps.html

http://msdn.microsoft.com/en-us/library/bb278211.aspx 


Post a custom field to VendTrans/CustTrans through journal

Post a custom field to VendTrans/CustTrans through journal

Here is the scenario
  1. You have added a custom field to your Customer/Vendor transactions table.
  2. You want to capture this field during the posting of a Customer/Vendor transaction from General Journal and post it to CustTrans/VendTrans.
How do you go about this?
It is not that complicated really, we just need to know what happens during the posting process. Let us assume we want to add a new field called VGRWeBelieve (type Enum NoYes) to VendTrans.
  1. First we need to capture the fields on journal lines. So we need to add the same field to the table LedgerJournalTrans.
  2. Next we need to expose this new field on the journal lines form. If you are modifying the General Journal then you would modify the form LedgerJournalTransDaily.
  3. Next we need to move it from LedgerJournalTrans to the voucher that posts the lines to VendTrans.
  4. This is done in the class VendVoucher.
  5. The method newVendVoucherJournal of VendVoucher allows us to pull data from LedgerJournalTrans to VendVoucher.
  6. VendVoucher extends CustVendVoucher so let us add the field VGRWeBelieve (and the parmVGRWeBelieve method) to the class CustVendVoucher.
  7. And then basically populate this field in newVendVoucherJournal method.
  8. Now that we have the data in a class property, we then need to transfer this to VendTrans record.
  9. VendTrans record is created in the method CustVendVoucher.initCustVendTrans.
  10. CustVendVoucher class basically transfers all local class field data to a map called CustVendTrans. This map is common to both CustTrans and VendTrans. Since our custom field only exists on VendTrans table, we also need to add it to CustVendTrans map and map it only under VendTrans to the corresponding VendTrans custom field.
  11. Now we are ready to assign the parmVGRWeBelieve property of CustVendVoucher to CustVendTrans.VGRWeBelieve in the method initCustVendTrans. Here we need to be a bit careful. Since this method is called for both CustTrans and VendTrans (basically customer and vendor account types) we have to only assign it if CustVendTrans is of type VendTrans. We can find that out by using the following condition if(custVendTrans.TabelId == tableNum(VendTrans)) then assign.
Code changes
TypeNameChanges
TableVendTransNew field VGRWeBelieve
TableLedgerJournalTransNew field VGRWeBelieve
FormLedgerJournalTransDailyAdd the field VGRWeBelieve to the form at appropriate location
MapCustVendTransAdd a new field called VGRWeBelieve
Create a mapping under VendTrans node between this field and the field added on vendTrans
ClassCustVendVoucherAdd the new field vgrWeBelieve to class declaration
Add a new parm method as follows
public VGRWeBelieve parmVGRWeBelieve(VGRWeBelieve _vgrWeBelieve = vgrWeBelieve)
{
vgrWeBelieve = _vgrWeBelieve;
return vgrWeBelieve;
}
Modify method initCustVendTrans and add the following code to it
If(custVendTrans.TableId == tableNum(VendTrans))
{
custVendTrans.VGRWeBelieve = vgrWeBelieve;
}
ClassVendVoucherModify the method newVendVoucherJournal and add the following code to it.
vendVoucher.parmVGRWeBelieve(_ledgerJournalTrans.VGRWeBelieve)

Tuesday, 10 May 2016

SharePoint Server 2016 server features look like



A. SharePoint Server 2016 server features look like

A.1. Central Admin look like


A.2. All Service Applications look like


A.3. Connect to Service Applications

A.4. Manage Databases Upgrade Status

A.5. Enable Features on existing sites

A.6. General Application Settings - Project Web App be intergrated with SharePoint Server 2016 and InfoPath Forms Services have been kept


A.7. Manage Form Templates

A.8. All InfoPath form templates look like

A.9. Integrated section with Office 365

A.10. Activate Yammer


A.11. Yammer be well to Activated

A.12.  Central Admin Security
New: [Approve or reject distribution groups]

A.13. New [Distribution Group] look like

A.14. Manage Accounts

A.15. Password Management Settings

A.16. Antivirus

A.17. Define blocked file types

A.18. Security for Web Part Pages

A.19. Self-service Site Collection Management 1

A.20. Self-service Site Collection Management 2


A.21. Information Rights Management

A.22. System Settings

A.23. Role Conversion

A.24. Edit Public Zone URLs

A.25. Manage Farm Features 1

A.26. Manage Farm Features 2

A.27. Left - Top menu with Yammer, OneDrive and Sites

A.28. OneDrive On-Premise, all Documents look like

A.29. OnDrive for Business On-Premise with Documents be shared with me look like

A.30.  Docs I am following

A.31. OneDrive for Business On-Premise with Site folders look like

A.32. Servers in Farm

A.33. Configure Send To Connections

A.34. Configure Send To Connections 2

A.35. Job Definitions by Service, Access services is example

A.36. Job Definitions by Web Application

A.37. Timer Job Status

A.38. Timer Job Status - Succeeded Status

A.40. Review problems and solutions


A.41. Content Databases

A.42.

A.43.

A.44.
A.45.
A.46.
A.47.
A.48.
A.49.
A.50.


B. Site Collection features look like

B.1. Default Home Page of SharePoint Server 2016 Beta 2 Team Site look like



B.2. Site Settings of Site Collection

B.3. Site Settings of Site Collection 2

B.4.
B.5.


B1. Browse to download page of SharePoint Server 2016 Beta 2

https://www.microsoft.com/en-us/download/details.aspx?id=49961

B2. Choose English version with name [SharePoint Server 2016 Beta 2 English.iso] or another language, can be a Chinese, Frenche, German, Japanese or Spanish version



B3. Download confirmation and Thank you from Microsoft


B4. Check if there isturn on Web Server (IIS) on the SharePoint Server 2016 or not


Labels

#veryusefulcode (1) AIF (8) AOT Maps (1) Args (1) Ax 2009 Reports (2) AX 2012 navigation (1) Ax 2012 Interview Questions (1) AX 7 (2) AX Architecture (1) Ax Backup (1) AX Workflow (2) AX2012 (1) AX2012 R2 (1) Ax2012R3 (1) AX2012R3 Dynamics Connector Step by Step Installation and Configuration (1) AX2012R3 EP Step by Step Installation and Configuration EP R3 (1) AX2012R3 HelpServer Step by Step Installation and Configuration (1) AX2012R3 Rapid Start Connector Step by Step Installation and Configuration (1) AX2012R3 Report Server and Analysis Server Step by Step Installation and Configuration (1) AX7 (1) Best practices (1) Blocking user to enter (1) Collection Classes (1) Container (1) D365FO (3) Data Migration Frame Work ax 2012R3 (1) Deleting duplicate Record from Table – Ax2012 (1) Delivery due date notification workflow in Ax 2012 (1) Development Steps EP (1) Dimensions (1) DIXF (1) DMF in Ax 2012 R3 (1) Dynamics Ax 2012 Interview Questions (1) DYNAMICS AX 2012 INTERVIEW QUESTIONS PART 2 (1) DYNAMICS AX 7 (1) EDT relation Migration Tool (1) EP AX 2012 (1) Ep Lookup (1) Error (1) Event Handler (1) F5 (1) File Handling (4) Filter on AX2012 Listpage (1) filtering (2) financial dimensions in AX 2012 (3) form (1) images (1) Installation and Configration (4) Installation and Configuration (11) Installation of Management Reporter 2012 for AX 2012 (1) Interaction class in ax 2012 (1) Interview Question (1) Interview Questions For Ax 2012 (1) Invent DIm (1) Jobs (2) license (1) List page and form menuitem enable code (1) Methods (1) microsoft Dynamics AX 365FO (1) Number Sequence Generation – AX 2012 (5) Number Sequence2012 (1) OLTP-OLAP (1) Passing Args (1) Passing form caller and menu item caller in ax 2012 (1) Passing Multiple Records Args (1) Posting in Ax 2012 (1) POSTING PURCHASE ORDER (1) Query (1) Query Filter Form (2) Query Ranges in X++ (1) Question and Answer (1) Report (1) Reports Controller class (1) RLS in ax 2009 (1) SALES ORDER IMPORT/EXPORT FRAMEWORK BY DMF (1) Security (1) security roles (1) Security Sysqueryrangeutil (1) Sharepoint 2016 (1) SQL SERVER (1) SSRS (2) SSRS Reports Controller class (2) Table collections & Virtual company (1) Time (1) TIPS AND TRICKS (1) Web service AIF (3) Web Services on IIS (AIF) Step by Step Installation and Configuration (1) workflow ax2012 (1) Workflow installation (1) Workflow Method (3) X++ (1)