bcquality/microsoft/knowledge/performance/avoid-commit-inside-loops.good.al
Jesper Schulz-Wedde 078b869e33
Add per-row AL performance guidance (#97)
* Add per-row performance guidance

Document SetAutoCalcFields for per-row FlowFields and direct writes on iterated records, with focused reviewer retrieval cues.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 85be3fc4-5253-47b8-ba1b-6b8fd188fcea

* Bound commit checkpoints by key range

Use a capped ordered query to discover each checkpoint watermark before locking and processing only that key range.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 85be3fc4-5253-47b8-ba1b-6b8fd188fcea

* Address performance retrieval review

Retrieve Commit-in-loop guidance precisely, process exact checkpoint key lists, and narrow clone-before-write discovery.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 85be3fc4-5253-47b8-ba1b-6b8fd188fcea

---------

Co-authored-by: Jesper Schulz-Wedde <jesper.schulzwedde@microsoft.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
2026-07-14 12:51:39 +02:00

60 lines
1.7 KiB
AL

query 50127 "Perf Customer Chunk"
{
QueryType = Normal;
OrderBy = ascending(CustomerNo);
elements
{
dataitem(Customer; Customer)
{
column(CustomerNo; "No.") { }
}
}
}
codeunit 50128 "Perf Sample CommitInLoop Good"
{
procedure NormalizeCustomerNames()
var
LastCustomerNo: Code[20];
begin
// The outer loop owns checkpoints; the per-row loop contains no Commit.
while NormalizeNextChunk(LastCustomerNo) do
Commit();
end;
local procedure NormalizeNextChunk(var LastCustomerNo: Code[20]): Boolean
var
Customer: Record Customer;
TempCustomer: Record Customer temporary;
CustomerChunk: Query "Perf Customer Chunk";
LastChunkCustomerNo: Code[20];
begin
CustomerChunk.TopNumberOfRows(500);
if LastCustomerNo <> '' then
CustomerChunk.SetFilter(CustomerNo, '>%1', LastCustomerNo);
CustomerChunk.Open();
while CustomerChunk.Read() do begin
TempCustomer.Init();
TempCustomer."No." := CustomerChunk.CustomerNo;
TempCustomer.Insert();
LastChunkCustomerNo := CustomerChunk.CustomerNo;
end;
CustomerChunk.Close();
if TempCustomer.IsEmpty() then
exit(false);
Customer.LockTable();
if TempCustomer.FindSet() then
repeat
if Customer.Get(TempCustomer."No.") then begin
Customer.Name := UpperCase(Customer.Name);
Customer.Modify();
end;
until TempCustomer.Next() = 0;
LastCustomerNo := LastChunkCustomerNo;
exit(true);
end;
}