bcquality/microsoft/knowledge/data-modeling/dimension-management-wiring.md
Michael Dieringer a28ba1a1d7 Address second round of Jesper Schulz-Wedde's review on PR #156
- dimension-management-wiring.md/.good.al: split into the two distinct
  models the article was conflating - master data (Default Dimension
  records via ValidateDimValueCode/SaveDefaultDim) vs. transactional/
  document data (a single Dimension Set ID assembled via AddDimSource +
  GetDefaultDimID, verified against BCApps' ExchRateAdjmtProcess.Codeunit.al).
  Added a compiling document-table example alongside the existing master
  table one.
- Deleted api-page-flowfields-must-be-calcfields (.md/.good.al/.bad.al):
  Microsoft's own FlowFields documentation states a FlowField used as a
  control's direct source expression is automatically calculated on any
  page - no API-page exception is documented, and none could be
  reproduced.
- prefer-email-module.bad.al/.md: Codeunit Mail has no Send/GetErrorDesc
  members; fixed to the real current 7-argument CreateMessage signature,
  and corrected the claim that the legacy path "still runs" - its base
  implementation no longer sends anything, only raises integration events.
- check-post-line-batch-pattern.md/.good.al: reframed from a universal
  invariant to the standard shape, naming the real Gen./Item/CA/Res./Job/
  Insurance/Mfg. Item/FA Jnl.-Check Line/-Post Line/-Post Batch codeunits
  it's based on. Added the missing Check Line companion codeunit so the
  good fixture is internally complete.
- test-data-must-be-random-and-complete.good.al: removed leftover
  "collision-free" wording contradicting the already-corrected article text.
- fixed-choice-set-must-use-enum-not-integer.md: removed the reintroduced
  state-count heuristic ("the line is the state count"), aligned with
  binary-choice-must-be-boolean.md's semantics-based distinction.
- namespace-must-be-verified-from-source.md: removed the false claim that
  the compiler and AL Language Server use different namespace-resolution
  rules.
- intrinsic-al-functions-must-use-modern-casing.md: removed the unverified
  claim that PascalCase is the VS Code formatter's default output.

Worklist completeness: added cues for the 8 rules in data-modeling,
testing, performance, and web-services that had none (Jesper's explicit
ask), plus the same gap in all 7 style rules from this PR (not explicitly
named this round, but the identical systemic issue) - 15 cues total across
al-data-modeling-review.md, al-testing-review.md, al-performance-review.md,
al-web-services-review.md, and al-style-review.md.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-21 22:26:33 +02:00

3.2 KiB

bc-version domain keywords technologies countries application-area
all
data-modeling
dimensions
dimensionmanagement
global-dimension
shortcut-dimension
default-dimension
validatedimvaluecode
getdefaultdimid
al
w1
all

Wire dimension support through DimensionManagement, not ad hoc fields

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

Description

Adding dimension support to a custom table is not just a matter of adding a Code[20] field, and master tables and document/transactional tables wire into Codeunit "Dimension Management" through two different models — treating them as one mechanism is itself the mistake this article corrects:

  • Master data (a custom master table, e.g. "Course") persists Default Dimension records: each shortcut dimension field validates through ValidateDimValueCode, then the result is saved via SaveDefaultDim, and DeleteDefaultDim removes them again in OnDelete. The master record itself carries no Dimension Set ID field.
  • Transactional/document data (a custom document or journal-line table) carries a single Dimension Set ID field — a pointer to a shared, deduplicated set of dimension values in Dimension Set Entry, assembled from whatever the document inherited plus whatever the user overrode. A document does not acquire that ID by calling SaveDefaultDim; it builds a source list with AddDimSource (naming the related master table and its key, e.g. Database::Customer), then calls GetDefaultDimID to compute a new Dimension Set ID that inherits the master's Default Dimension records. Editing a shortcut dimension field directly on the document validates through ValidateShortcutDimValues, which updates the same Dimension Set ID in place rather than writing a separate Default Dimension record.

Skipping the model that actually matches the table's kind produces a field that looks correct in the designer but silently fails to save, validate, or carry through to postings — or, for a document, one that never picks up the customer's/vendor's own dimensions at all.

Best Practice

For a master table, validate each shortcut dimension field through ValidateDimValueCode, save the result with SaveDefaultDim, and delete the matching Default Dimension records in OnDelete.

For a document table, when the field that attaches the document to a master record changes (e.g. Customer No.), call AddDimSource naming that master table and key, then GetDefaultDimID to compute the document's new Dimension Set ID, inheriting the master's Default Dimension records. Validate the document's own Shortcut Dimension fields through ValidateShortcutDimValues, which updates that same Dimension Set ID rather than persisting a separate Default Dimension record.

See sample: dimension-management-wiring.good.al.

Anti Pattern

Adding a dimension-looking field with only a TableRelation to Dimension Value, and no call into DimensionManagement at all. The field accepts input but never becomes a real Default Dimension record, so it does not validate against blocked values and does not flow into postings.

See sample: dimension-management-wiring.bad.al.