bcquality/microsoft/knowledge/upgrade/datatransfer-skips-triggers-and-subscribers.md
Jesper Schulz-Wedde 5706959e4a
Fix lifecycle compatibility guidance (#93)
* Fix lifecycle compatibility guidance

Correct high-confidence Business Central guidance and samples for upgrade tags, collectible errors, trigger semantics, obsoletion, events, interfaces, API contracts, and test transactions.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: e05a43e7-6448-4d67-9c73-798523f5d945

* Address guidance review findings

Gate SecretText guidance to BC23 and clarify that the collectible-error sample intentionally emits a message-only blocking aggregate.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: e05a43e7-6448-4d67-9c73-798523f5d945

---------

Co-authored-by: Jesper Schulz-Wedde <jesper.schulzwedde@microsoft.com>
2026-07-14 11:26:16 +02:00

2.1 KiB

bc-version domain keywords technologies countries application-area
21..
upgrade
datatransfer
validate-trigger
event-subscriber
side-effects
business-logic
al
w1
all

DataTransfer does not fire validation triggers or event subscribers

Description

DataTransfer writes sets directly at the database layer, so row-based triggers and events do not run. For CopyFields, that includes the table OnModify trigger and OnBeforeModifyEvent/OnAfterModifyEvent; direct field assignment also does not call field OnValidate or its validation events. These are separate behaviors: Record.Validate(Field, Value) runs field validation, while Record.Modify(true) runs the table OnModify trigger. Calling Modify(true) does not retroactively validate assigned fields.

For new fields and tables added in the same change this is fine: nothing yet depends on the validation. For pre-existing fields with validation logic, DataTransfer quietly bypasses business logic that may be load-bearing for posting, calculation, or integration scenarios.

Best Practice

Use DataTransfer when set-based transfer is safe and row-level business logic is intentionally unnecessary — initial population of a new field is the canonical case. When an existing field's validation must run, loop through records and call Validate(Field, Value); if the table's modify trigger must also run, follow with Modify(true). If performance requires DataTransfer, document exactly which field-validation and row-modification triggers or subscribers are intentionally bypassed and verify that derived data remains correct.

See sample: datatransfer-skips-triggers-and-subscribers.good.al.

Anti Pattern

Reaching for DataTransfer to update an existing field with non-trivial OnValidate or OnModify logic, without confirming that both validation and row-modification subscribers can be skipped. Replacing it with only Modify(true) is also incomplete when field validation is required; call Validate for that field first.

See sample: datatransfer-skips-triggers-and-subscribers.bad.al.