bcquality/community/knowledge/performance/deleteall-skips-ondelete-unless-runtrigger.md
Jeremy Vyska 4119417ce4
Some checks failed
Validate knowledge index / validate-index (push) Has been cancelled
Validate frontmatter and structure / validate (push) Has been cancelled
Add 15 community knowledge articles from BC Code Intel ingest (#66)
* Add 15 community knowledge articles from BC Code Intel ingest

Ingests net-new /community knowledge from BC Code Intelligence, surviving
the admission test, gray-zone salvage, and dedup against the full corpus.

Domains: ui (6), error-handling (3), performance (2), upgrade (1),
appsource (1), security (1), telemetry (1). The two BC24 No. Series
migration drafts are merged into one article.

Adds good/bad AL samples for the clean-fit articles (error-handling,
performance, security, telemetry). UI and appsource remain knowledge-only.

Validator and knowledge-index checks pass (207 articles).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Correct SetLoadFields JIT-load article to match MS docs

The draft claimed accessing an unlisted field "reloads the entire row"
per record. Microsoft's partial-records docs say otherwise: the platform
does an implicit Get that loads the missing field(s), and in a direct var
loop the first JIT updates the enumerator so later iterations do not
re-load. The genuine per-row penalty is the pass-by-value case, where the
copy's enumerator is not updated.

Rewrite the article around JIT loading and the by-value footgun, rename
the slug from ...full-reload to ...jit-load, and fix the good/bad samples
to demonstrate the by-value repetition accurately.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Jeremy Vyska <jeremy@sparebrained.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 14:31:50 +02:00

1.7 KiB

bc-version domain keywords technologies countries application-area
all
performance
deleteall
ondelete
run-trigger
set-based-delete
bulk-delete
triggers
validation
al
w1
all

DeleteAll skips OnDelete unless you pass RunTrigger

Contributions welcome — open a PR to refine or extend this article.

Description

Record.DeleteAll() — equivalently DeleteAll(false) — translates to a single set-based SQL DELETE and does not run AL OnDelete triggers or field/table validations. Only database-level referential constraints still apply. To run OnDelete logic you must call DeleteAll(true), which then deletes record-by-record and forfeits the set-based performance, making it equivalent to a FindSet loop calling Delete(true). The common misconception, which training data reproduces, is that DeleteAll iterates and fires OnDelete per record; it does not. (Parameterless Delete() likewise defaults to Delete(false) and skips OnDelete.)

Best Practice

Use DeleteAll() / DeleteAll(false) for bulk deletion only when no AL OnDelete cleanup is required — it is the fast, set-based form. When OnDelete logic must run (cascading deletes, ledger cleanup, integration events), pass DeleteAll(true) and accept the row-by-row cost, or refactor the cleanup to run explicitly before the bulk delete.

Anti Pattern

Calling DeleteAll() and assuming dependent records, integration events, or validation side effects are handled by OnDelete. The deletion succeeds but the AL-side cleanup never runs, leaving orphaned data — and adding a manual FindSet/Delete loop "for safety" reintroduces the per-record cost the set-based form was chosen to avoid.