- dimension-management-wiring: SaveDefaultDim's third argument is the shortcut dimension number (1-8), not the field's AL field ID; the fixture passed FieldNo(...) = 10. GetDefaultDimID's InheritFromDimSetID must be 0 when recomputing after the linking record changes, not the document's existing Dimension Set ID (which would retain the previous customer's leftover dimensions). Verified against DimensionManagement.Codeunit.al and BankDepositHeader.Table.al in the BCApps reference clone. - check-post-line-batch-pattern: "Post Line writes exactly one line to the ledger" overclaimed - Gen. Jnl.-Post Line alone calls InsertGLEntry from a dozen call sites (balancing entry, VAT, currency rounding, deferrals) and can write several G/L Entries per journal line. Reworded to "posts exactly one journal line" and softened the "distinct, non-overlapping responsibilities" absolute. - namespace-must-be-verified-from-source.bad.al: dropped the "resolves in a local build, fails in VS Code" comment (taught an inherent compiler/language-server disagreement that isn't real); reframed as stale/cached symbols, matching the prose fix already made. - file-datatype-saas.good.al: replaced the deprecated 5-argument UploadIntoStream overload with the current 2-argument one, and actually staged through TempBlob as the article's own Best Practice instructs (the declared TempBlob variable was previously unused). - test-data-must-be-random-and-complete: no longer treats a short-but-valid value as defective merely for being "underfilled" - AL field lengths are maxima, not minimums. Scoped to missing values or a scenario with an explicit length/format requirement (e.g. a truncation test). Updated the al-testing-review.md routing cue to match. - stored-derived-fields-must-not-be-exposed-directly: stopped mandating source-field exposure as part of the core pattern: the good fixture exposed only one of the derived value's two inputs (Hours Used, not Budgeted Hours), making the claimed "so the consumer can verify it" impossible. Reframed as an optional, all-or-nothing addition and fixed the fixture to expose both inputs. Rebased onto upstream/main to resolve conflicts in al-breaking-changes-review.md, al-data-modeling-review.md, al-performance-review.md, and al-style-review.md against merged PRs #148 and #153; all sides' worklist tokens/cues retained.
3.7 KiB
| bc-version | domain | keywords | technologies | countries | application-area | |||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
data-modeling |
|
|
|
|
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 viaSaveDefaultDim, andDeleteDefaultDimremoves them again inOnDelete. BothValidateDimValueCodeandSaveDefaultDimtake the shortcut dimension number (1-8, matchingGeneral Ledger Setup's "Shortcut Dimension N Code" fields) as their first/third argument respectively — not the AL field ID of the table field being validated. The master record itself carries noDimension Set IDfield. - Transactional/document data (a custom document or journal-line table) carries a single
Dimension Set IDfield — a pointer to a shared, deduplicated set of dimension values inDimension Set Entry, assembled from whatever the document inherited plus whatever the user overrode. A document does not acquire that ID by callingSaveDefaultDim; it builds a source list withAddDimSource(naming the related master table and its key, e.g.Database::Customer), then callsGetDefaultDimIDto compute a newDimension Set IDthat inherits the master's Default Dimension records. Editing a shortcut dimension field directly on the document validates throughValidateShortcutDimValues, which updates the sameDimension Set IDin 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. Pass 0 for GetDefaultDimID's InheritFromDimSetID argument in this case — passing the document's existing Dimension Set ID instead inherits whatever dimensions were already in it, so a value the previous linked record supplied can survive into the new one even where the new record has no default for that dimension. Validate the document's own Shortcut Dimension fields through ValidateShortcutDimValues, which updates that same Dimension Set ID in place 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.