Use SetAutoCalcFields for loops (PC0035)

Default SeverityWarning
CategoryPerformance
Code ActionYes (QuickFix)
Supports Fix AllYes
Ignores Obsolete PendingNo

When CalcFields is called inside a loop, each iteration generates a separate SQL query per FlowField. This is a well-documented performance anti-pattern. Calling SetAutoCalcFields before the loop tells the runtime to include FlowField calculations in the main SELECT query that fetches each record, eliminating the extra round trips.

A code fix is available for this diagnostic.

Example

The following code calls CalcFields on every iteration of a FindSet loop:

codeunit 50100 MyCodeunit
{
    procedure MyProcedure()
    var
        Customer: Record Customer;
    begin
        Customer.FindSet();
        repeat
            Customer.CalcFields("Balance (LCY)");
        until Customer.Next() = 0;
    end;
}

To fix this, replace the CalcFields call with SetAutoCalcFields before the loop:

codeunit 50100 MyCodeunit
{
    procedure MyProcedure()
    var
        Customer: Record Customer;
    begin
        Customer.SetAutoCalcFields("Balance (LCY)");
        Customer.FindSet();
        repeat
            // Balance (LCY) is now automatically calculated on each record fetch
        until Customer.Next() = 0;
    end;
}

When the diagnostic is reported

The rule fires when all of the following conditions are true:

  • A CalcFields invocation is found inside a loop body
  • The CalcFields call is on the same record variable that drives the loop
  • The loop is one of: FindSet/Find + repeat...until, while...do, or a report OnAfterGetRecord trigger

When the diagnostic is NOT reported

  • The CalcFields call is on a different variable than the one driving the loop
  • The CalcFields call is outside any loop
  • The CalcFields call is in a sub-procedure (cross-method tracking is out of scope for v1)
  • The record is read without a loop (e.g., after Get or FindFirst)

Code fix

The ALCops: Use SetAutoCalcFields before loop code fix:

  1. Inserts a SetAutoCalcFields call with the same field arguments before the loop (or before the FindSet/Find statement)
  2. Removes the CalcFields call from inside the loop body

When multiple CalcFields calls exist for the same variable in the same loop, each is handled individually by the fix-all provider.

See also