bcquality/microsoft/knowledge/performance/use-findset-readonly-by-default.md
Jesper Schulz-Wedde 9a4198eb28 Add [all] sentinel to bc-version; apply to version-agnostic knowledge
Most of the corpus — FindSet/SetLoadFields/CalcFields patterns, permission
sets, SingleInstance codeunits, DataClassification, IsolatedStorage,
transaction scope, SecretText — describes BC platform behaviour that is
identical across supported versions. The seed [26..28] range on every
file implied a version-specificity the content does not actually have,
and there was no way to express "applies to every version" in the
schema the way [w1] and [all] already do for countries and
application-area.

Extend the v1 schema with a universal sentinel for bc-version, parallel
to the sentinels already defined for the other dimensions:

  bc-version: [all]         # applies to every BC version

[all] is mutually exclusive with explicit versions. Range shorthand
([26..28]) and explicit lists ([26, 27, 28]) continue to work for files
genuinely tied to a version-gated API or deprecation.

Update read.md (field definition, matching semantics, partial-context
rule), write.md (default to [all], use ranges only with a concrete
reason), README.md (frontmatter example), and the CI validator. All
forty existing knowledge files and the three action skills convert to
[all]; none of the current content is version-gated. Validator passes.
2026-04-23 16:00:03 +02:00

27 lines
1.2 KiB
Markdown

---
bc-version: [all]
domain: performance
keywords: [findset, lock, locktable, readonly, update]
technologies: [al]
countries: [w1]
application-area: [all]
---
# Use FindSet in read-only mode by default
## Description
FindSet has two modes: FindSet() and FindSet(false) are read-only and take no write lock; FindSet(true) calls LockTable before fetching. Write locks are expensive and hold for the remainder of the transaction, so passing `true` when you do not intend to modify the records increases contention under load.
## Best Practice
Call FindSet with no arguments when the loop only reads field values. Pass `true` only when the same loop is expected to call Modify, Delete, or Rename on the record, and the correctness of the operation depends on the table being locked for the full iteration.
See sample: `use-findset-readonly-by-default.good.al`.
## Anti Pattern
Writing FindSet(true) reflexively for every iteration forces the platform to take a LockTable on every call, even when the loop only reads values. The older two-parameter signature `FindSet(ForUpdate, UpdateKey)` is obsolete and must not be used.
See sample: `use-findset-readonly-by-default.bad.al`.