bcquality/community/knowledge/data-modeling/validate-table-relation-false-suppresses-rename-propagation.md
Stefan Maron e00ef8ad94 knowledge(data-modeling): TableRelation delete/rename asymmetry and the xRec before-image contract
Three related concerns, each proven by executable tests rather than recall.
They were extracted from a real defect that shipped through a six-reviewer
panel undetected, which is the admission test passing on behavior rather than
on theory.

owning-table-must-delete-dependents-in-ondelete
  AL has no cascading delete. What makes it missable is an asymmetry: the
  platform DOES keep references correct on rename via TableRelation, so a
  developer who learns that and generalizes it to delete ships orphans. Also
  notes the permission trap (delete rights needed on the dependent table, not
  just the parent).

validate-table-relation-false-suppresses-rename-propagation
  The non-obvious half. The property name implies input validation only, but
  disabling it also switches off rename propagation. Verified against a parent
  renamed once while a child held three fields: a normal relation (follows),
  the same relation with validation disabled (does NOT follow), and a field
  with no relation at all (does not follow) — the third being the control that
  proves the test can detect a non-propagating field.

xrec-is-a-before-image-only-in-some-triggers
  Corrects both the naive belief that xRec is always the previous record and
  the folk rule that it 'only works from a page'. The behavior is per-trigger:
  a genuine before-image in OnRename and OnDelete regardless of driver, a
  mirror of Rec in OnInsert/OnModify when driven from code, and a real
  before-image in those two only when a page drove the write. That last
  asymmetry is why an OnModify comparison against xRec passes manual page
  testing and silently no-ops in a job queue.

Targets /community per CONTRIBUTING — general BC knowledge, not fork-specific.
Frontmatter validator clean; Test-ReviewFixtures passes (32 cases, 16 leaves).
2026-08-05 13:46:41 +02:00

2.8 KiB

bc-version domain keywords technologies countries application-area
all
data-modeling
validatetablerelation
table-relation
rename
onrename
propagation
dangling-reference
soft-relation
al
w1
all

ValidateTableRelation = false suppresses rename propagation, not just input validation

Description

Renaming a record updates it in all other locations that reference it through a TableRelation, with no code. That guarantee has two preconditions, and a field failing either one is silently left holding a key that no longer exists.

First, a TableRelation must exist. A field whose value is constructed or computed — a composite key, or a value derived from several fields of the target — cannot declare one, so nothing propagates. The field is still a foreign key in intent, but the platform treats it as an opaque value.

Second, and far less obvious: the relation must not carry ValidateTableRelation = false. The property name implies it only governs input validation, so it looks safe to disable on a field populated by code that already knows the target is valid. It is not. Disabling it also switches off rename propagation. The relation still documents intent and still drives lookups, but it no longer keeps the stored value correct.

Both failures are quiet: no error at rename time, and in the first case no input validation either, so a wrong value is never rejected on write.

This is verified behaviour, not inference. A parent renamed once against a child holding three fields — a normal relation, the same relation with ValidateTableRelation = false, and a field with no relation — updates only the first.

See also owning-table-must-delete-dependents-in-ondelete.md for the delete half of this asymmetry, and xrec-is-a-before-image-only-in-some-triggers.md for why OnRename is the one trigger where a hand-written fix-up is reliable.

Best Practice

Leave ValidateTableRelation at its default wherever the stored value must stay correct across a rename. When it must be disabled, or when the relationship cannot be expressed as a TableRelation at all, the table owning the referenced key carries an explicit OnRename that repoints the dependents itself.

See sample: validate-table-relation-false-suppresses-rename-propagation.good.al.

Anti Pattern

ValidateTableRelation = false added to silence a validation error, on a field expected to keep tracking its target. The field stops being maintained on rename, and the defect surfaces much later as a reference to a key that no longer exists.

Detection signal: any ValidateTableRelation = false on a field that also declares a TableRelation. Ask what repoints the value when the target is renamed; if the answer is "the platform", the finding stands.

See sample: validate-table-relation-false-suppresses-rename-propagation.bad.al.