Use ReadIsolation instead of LockTable (LC0031)
This rule flags calls to LockTable() and suggests replacing them with ReadIsolation := IsolationLevel::UpdLock.
While the change in code is small, the difference at the platform level is significant. LockTable() modifies the global session state: once called on any record variable, every subsequent read against that table — on any variable instance — will acquire an update lock for the remainder of the transaction. This means an event subscriber, a FlowField calculation, or unrelated code further down the call stack can end up locking rows it never intended to touch.
ReadIsolation, introduced in Business Central 2023 wave 1 (v22), works differently. It sets the isolation level on the specific record variable only. Other variables of the same table remain unaffected, keeping lock scope tight and predictable.
There is another reason to make the switch: tri-state locking (default from v25 onward) falls back to pessimistic two-state locking the moment LockTable() is called anywhere in the transaction. Replacing LockTable() with ReadIsolation preserves the tri-state benefits — fewer locks, higher concurrency, and fewer lock timeouts across the system.
A code fix is available for this diagnostic.
Example
The following procedure locks the entire G/L Entry table for the rest of the transaction just to read the last entry number:
codeunit 50100 MyCodeunit
{
procedure GetNextEntryNo(): Integer
var
GLEntry: Record "G/L Entry";
begin
GLEntry.LockTable();
GLEntry.FindLast();
exit(GLEntry."Entry No." + 1);
end;
}With ReadIsolation, only this specific variable acquires the lock. Any other code reading from G/L Entry later in the transaction remains unaffected:
codeunit 50100 MyCodeunit
{
procedure GetNextEntryNo(): Integer
var
GLEntry: Record "G/L Entry";
begin
GLEntry.ReadIsolation(IsolationLevel::UpdLock);
GLEntry.FindLast();
exit(GLEntry."Entry No." + 1);
end;
}Deep dive
The articles below explore the locking differences in detail, including real-world examples, SQL-level traces, and the interaction with tri-state locking:
- Record instance isolation level
— Microsoft Learn reference for
ReadIsolationand isolation levels - Locking Scope: Differences between LockTable and ReadIsolation
— SQL-level analysis showing how
LockTableleaks locks to unrelated code - Optimized Locking Feature vs Dynamics 365 Business Central — Tri-state locking, RCSI, and transaction isolation in practice
- Rec.LockTable: Good Practice or Bad Practice? — How a long-standing best practice became an anti-pattern
- Tri-State Locking and Isolation Levels — Overview of two-state vs. tri-state locking and practical tips
- Control Database Locking Behavior
— Walkthrough of the
ReadIsolationmethod and isolation level options