Welcome back to the series on performance patterns in AL programming! 🎊



Lazy evaluation

Lazy evaluation is an evaluation strategy that delays the computation of an expression until its value is actually needed. This approach can significantly enhance performance by avoiding unnecessary calculations and reducing resource consumption. In AL programming, lazy evaluation can be particularly beneficial in scenarios where certain computations are expensive and may not always be required.

if  Customer.IsBlocked() and (Customer.CalcAvailableCredit() > 0) then
// Do something

        if Customer.IsBlocked() then
if Customer.CalcAvailableCredit() > 0 then
// Do something

Here we had one fast procedure which is IsBlocked, which checks only if Customer is blocked and one heavier procedure CalcAvailableCredit which calculates Total Amount LCY with Cac Fields and so on.

In first way which we said Wrong, then both procedures will execute no matter if first one is immediately false. On that way it would unnecessarily execute additional procedures in condition which wouldn’t be needed.

On the other side, in some cases you would like to execute those procedures anyway no matter if they result true or false, there are some scenarios in base app. Again, its up from case to case what you would like to accomplish.

What about ‘or’ condition?

if  Customer.IsBlocked() or (Customer.CalcAvailableCredit() > 0) then
   // Do something
if true in [Customer.IsBlocked(), Customer.CalcAvailableCredit() > 0] then
   // Do something

In this case if Customer is Blocked it will immediately exit, without executing second procedure.


Text Builder when working with text

The TextBuilder data type in AL programming is a powerful tool for efficient text manipulation. It acts as a lightweight wrapper for the .NET implementation of StringBuilder, allowing you to perform repeated modifications to a string without creating new objects in memory. This can significantly boost performance, especially when concatenating many strings together in a loop.

repeat
   CustomerNames += Customer.Name + ', ';
until Customer.Next() = 0;
repeat
   CustomerNames.Append(Customer.Name + ', ');
until Customer.Next() = 0;

Query instead of nested loops

Using queries instead of nested loops can significantly improve performance, especially when dealing with large datasets. Queries allow you to join tables and retrieve data in a single operation, reducing the overhead associated with multiple loops and record retrievals.

Vendor.FindSet();
repeat
    PurchInvHeader.SetRange("Buy-from Vendor No.", Vendor."No.");
    if PurchInvHeader.FindSet() then
        repeat
            PurchInvLine.SetRange("Document No.", PurchInvHeader."No.");
            if PurchInvLine.FindSet() then
                repeat
                    if PurchInvLine.Type = PurchInvLine.Type::Item then begin
                        Item.Get(PurchInvLine."No.");
                        // Do something
                    end;
                until PurchInvLine.Next() = 0;
        until PurchInvHeader.Next() = 0;
until Vendor.Next() = 0;
PurchInvItemsByVendors.Open();

while PurchInvItemsByVendors.Read() do begin
    // Do something
end;

PurchInvItemsByVendors.Close();

Datatransfer when moving data in upgrade

The DataTransfer object can only be used in upgrade code and it’ll throw a runtime error if used outside of upgrade codeunits.

Using the DataTransfer object in install codeunits, it’s checked that the install code is running inside the scope of installing an extension, meaning that the install code is triggered from the OnInstallAppPerDatabase and OnInstallAppPerCompany events that are emitted during installation.

The DataTransfer object can’t be used on the following tables:

  • Non-SQL tables
  • System tables
  • Virtual tables
  • Audited tables as the destination
  • Obsoleted tables as the destination

The DataTransfer object can be used for essentially two operations:

  • Copy data from one or more fields in a table to fields another table. A typical scenario is when you’ve made a field obsolete, but also to set default field values (similar to Record.ModifyAll()).
  • Copy data from entire rows in a table to rows in another table. A typical scenario is when you’ve made a table obsolete.

There are multiple examples on Microsoft Docs:

Transferring data between tables using DataTransfer – Business Central | Microsoft Learn

Make sure you read there Performance part of those examples with accurate explanation.


Stay tuned for more detailed analyses and practical examples in the upcoming parts of this series. Let’s continue this journey together and see where it leads us. Thank you for your continued support and engagement! 🚀

Categorized in: