Dictionary In Business Central

 A dictionary is an object type that represents a collection of keys and values. You can think of it as a two-field table where the first field is the key, and the second field is the value:

In AL a dictionary can be defined as the following:

var

Dictionary1: Dictionary of [Integer, Text];

Dictionary2: Dictionary of [Code [20], Decimal];


Dictionary3: Dictionary of [Date, Guid];


As you can see, there are endless combinations for creating a dictionary. The only restriction is that we can only use simple data types, the same as lists.

Although dictionaries can be more complex to understand than lists, there are only 10 methods available to use whereas lists have 18.

Here is the list of them.

The following methods are available on instances of the Dictionary data type.

Method name Description

Add(TKey, TValue) Adds the specified key and value to the dictionary.

ContainsKey(TKey) Determines whether the Dictionary contains the specified key.

Count()                 Gets the number of key/value pairs contained in the Dictionary.

Get(TKey, var TValue)         Gets the value associated with the specified key.

Get(TKey)                 Gets the value associated with the specified key.

Keys()                 Gets a collection containing the keys in the Dictionary.

Remove(TKey)         Removes the value with the specified key from the Dictionary.

Set(TKey, TValue)         Sets the value associated with the specified key.

Set(TKey, TValue, var TValue) Sets the value associated with the specified key.

Values()                 Gets a collection containing the values in the Dictionary.

Dictionaries work together with lists. They work together because when you need to retrieve the keys of a dictionary, the keys are actually a list.

So if you haven´t checked the introduction to lists, make sure to do it here:

When Should We Use A Dictionary?


Most of the time you can use a dictionary to replace temporary tables. As Microsoft suggests:

Previously in C/AL, one would have typically used an in-memory temporary table to create a key-value data structure, as shown in the code below. In AL you use the Dictionary Data Type instead.

This kind of approach, when applied, can increase performance significantly. It´s a faster approach than temporary tables. Erik has a great post about it. He compares performance between temporary tables and dictionaries. Make sure to check it out:

Erik Hougaard post: What’s faster than temporary tables?

Use Case Example 1


In the second method of the image below (‘GetCustDictionary’) we can use ‘if CustDictionary.Add() then;‘ to see if a customer can be added to a dictionary. If it´s not already in the dictionary, it will add it.

After that, we return the dictionary and loop through it. With CustDictionary.Keys() we get a list of the keys. Then, we can loop using foreach.

procedure SendMail(Customer: Record Customer)

var
CustomerNo: Code [20];
CustDictionary: Dictionary of [Code [20], Code [20]];
begin
CustDictionary := GetCustDictionary (Customer);
foreach CustomerNo in CustDictionary.Keys() do begin SendMailToCust (CustomerNo);
end;
end;
1 reference
local procedure GetCustDictionary Customer: Record Customer): Dictionary of [Code [20], Code [20]]
var
CustDictionary: Dictionary of [Code [20], Code [20]];
begin
if Customer.FindSet() then
repeat
if CustDictionary.Add(Customer."No.", Customer. "No.") then;
until Customer.Next() = 0;
exit (CustDictionary);
end;


Use Case Example 2


We can use a dictionary inside another dictionary. This way, we can replace a temporary table where more than two fields are needed.

In this example, you can see how we create a dictionary (DetailItemDict) of Description, Base Unit Of Measure and Unit Price. This information is stored in a dictionary that will be part of a bigger one (ItemDictionary).

The bigger one will hold Item numbers in the keys and DetailItemDict in the values.


local procedure GetItemDict(): Dictionary of [Code[20], Dictionary of [Integer, text]];
var
Item: Record Item;
ItemDictionary: Dictionary of [Code [20], Dictionary of [Integer, text]]; DetailItemDict: Dictionary of [Integer, Text];
begin
if Item.FindSet() then
repeat
    DetailItemDict.Add(1, Item.Description);
    DetailItemDict.Add(2, Item. "Base Unit of Measure");
    DetailItemDict.Add(3, format(Item."Unit Price"));
    ItemDictionary.Add(Item."No.", DetailItemDict);
    Clear (DetailItemDict);
until Item.Next() = 0;
exit(ItemDictionary);
end;


In this table, you can see a visual representation of what the process is doing. We only use DetailItemDict to store the values for each Item. Then, assign it to the ItemDictionary.


In order to retrieve the values, we have created two nested loops. One for looping through the dictionaries, we do it to get each dictionary that holds the detail values inside. And one to retrieve the datails in each dictionary.


procedure GetDictValues()
var
ItemDictionary: Dictionary of [Code [20], Dictionary of [Integer, text]]; Detail: Text;
Dict: Dictionary of [Integer, text];
ItemNo: Code [20];
i: Integer;
begin
ItemDictionary := GetItemDict();
i := 1;
foreach Dict in ItemDictionary.Values() do begin foreach Detail in Dict.Values() do begin
end;
end;
ItemDictionary.Keys.Get(i, ItemNo);
Message (Format (ItemNo) + ':' + Detail);
i += 1;
end;

No comments:

Post a Comment