bcquality/microsoft/knowledge/performance/avoid-cloning-records-before-modify-delete-in-loops.md
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

1.7 KiB

bc-version domain keywords technologies countries application-area
all
performance
clone
clone-before-write
copy
gettable
by-value
copied-record
writing-helper
al
w1
all

Avoid cloning records before Modify or Delete in loops

Description

Microsoft's AL database-method performance guidance states that cloning an iterated record before Modify or Delete restarts the SQL SELECT and issues an extra SQL statement for every row. The runtime treats Record.Copy, RecordRef.GetTable, and passing a record by value to a writing helper as clones in this situation.

Best Practice

Use FindSet(true) when the loop writes the traversed rows, and call Modify or Delete on that iterating record variable. If generic code is required, open and iterate the RecordRef directly instead of calling GetTable for each typed record. Keep a per-row loop when validation or row-specific behavior is required; this rule does not imply that ModifyAll or DeleteAll is equivalent.

See sample: avoid-cloning-records-before-modify-delete-in-loops.good.al.

Anti Pattern

Inside an active traversal, copy the current row, convert it with RecordRef.GetTable, or pass it without var to a helper, then call Modify or Delete on that clone. Do not flag read-only snapshots, temporary records, or copies used to write a different target table; the documented extra-statement concern is clone-before-write on the traversed table.

See sample: avoid-cloning-records-before-modify-delete-in-loops.bad.al.