bcquality/microsoft/knowledge/performance/calcsums-instead-of-calcfields-in-loop.md
Jesper Schulz-Wedde b6da405376 Improve partner onboarding and documentation navigation
Lead with a complete plugin quick start and add task-oriented usage, troubleshooting, customization, and contribution guides. Preserve the broader plugin framing, correct conflicting contract guidance, support Agents folder reviews, and align repository validation. Convert existing sample references to clickable links without changing knowledge rules.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-09-09 17:25:29 +02:00

1.8 KiB

bc-version domain keywords technologies countries application-area
all
performance
calcfields
calcsums
loop
flowfield
n-plus-one
aggregation
al
w1
all

Use CalcSums to aggregate, not CalcFields inside a loop

Description

CalcFields materializes FlowField values for one record. Each call against a persistent table is "a separate SQL query"; running it inside a repeat ... until Next() = 0 over a large table issues one query per row on top of the iteration itself. CalcSums answers the same aggregation question — "give me the sum of this FlowField over the filtered set" — as a single SQL statement. Per the upstream guidance, CalcFields inside loops on large persistent tables is "a performance problem"; the aggregation form is CalcSums().

Best Practice

When the procedure totals a FlowField (or several) across a filtered set, set the filters, then call CalcSums("Field 1", "Field 2", ...). The platform issues one query; the result is read off the record's FlowField slot. Single CalcFields outside loops is fine, and CalcFields on the current row in a page's OnAfterGetRecord or in OnValidate is the standard pattern — those are per-action, not per-row over a large set.

See sample: calcsums-instead-of-calcfields-in-loop.good.al.

Anti Pattern

if CustLedgerEntry.FindSet() then repeat CustLedgerEntry.CalcFields("Remaining Amount"); Total += CustLedgerEntry."Remaining Amount"; until CustLedgerEntry.Next() = 0; — exactly the upstream-flagged shape. The iteration is the cheap part; the per-row CalcFields is what scales linearly with table size.

See sample: calcsums-instead-of-calcfields-in-loop.bad.al.