In this video, I take a look at the ModifyAll command, discussing why I rarely use it. Check it out:

In this video, Erik explores the ModifyAll function in AL for Business Central — a powerful command that’s been around since the beginning, but one that is frequently misunderstood or misused. He walks through how it works, what it does (and doesn’t do), and why he rarely reaches for it in practice.
What is ModifyAll?
ModifyAll is a function on the Record type in AL that allows you to update a single field on every record matching the current filters — all in one operation. The basic syntax looks like this:
Rec.ModifyAll(FieldName, NewValue, RunTrigger);
The three parameters are:
- Field — The field you want to modify (typed as “Joker” internally, meaning it accepts any field reference)
- Value — The new value to assign. The type of this parameter is determined by the field you selected. If the field is a Text field, you pass a text value; if it’s an Integer field, you pass an integer, and so on.
- RunTrigger — A Boolean parameter (default
false). Iftrue, the code in theOnModifytrigger is executed. Iffalse, theOnModifytrigger is skipped entirely.
A Note on the “Joker” Type
You’ll notice in IntelliSense that the field and value parameters are listed as type “Joker.” This is an internal AL type that you can’t declare yourself — you can’t create a variable of type Joker. It simply means that the function accepts any type for that parameter, with the actual type being determined contextually by the field you pass in.
The First Gotcha: ModifyAll Does NOT Run Field Validation
This is the single most important thing to understand about ModifyAll. When the RunTrigger parameter is set to true, the OnModify trigger on the record is executed — but the OnValidate trigger on the field is never executed.
Erik demonstrates this by modifying the Name field on Vendor records. The Name field has validation logic that populates the Search Name field. After running ModifyAll with RunTrigger set to true, the Search Name field remained blank — proving that the field’s OnValidate trigger was never called. In contrast, manually typing into the Name field in the UI immediately updates Search Name because the validate trigger fires.
This is where many developers get tripped up: they expect ModifyAll to behave like assigning a value via Validate, but it doesn’t. It only assigns the raw value to the field.
The Second Gotcha: Multiple ModifyAll Calls Loop Multiple Times
A common pattern Erik sees is developers calling ModifyAll multiple times in sequence to update several fields:
Rec.ModifyAll(Name, '123 Best Street', true);
Rec.ModifyAll(Address, '234 Another Street', true);
While this works functionally, it’s very inefficient. To understand why, consider what ModifyAll is doing behind the scenes. A single ModifyAll call is essentially equivalent to:
if Rec.FindSet(true) then
repeat
Rec.Name := '123 Best Street';
Rec.Modify(true);
until Rec.Next() = 0;
So two ModifyAll calls means the system loops through every matching record twice, modifying each record two separate times. That’s double the database writes and double the trigger executions.
The Better Approach: Use a FindSet Loop
Instead of calling ModifyAll multiple times, you should write a single loop where you can update multiple fields, call Validate where needed, and issue a single Modify per record:
Rec.SetRange();
Rec.SetFilter();
if Rec.FindSet(true) then
repeat
Rec.Validate(Name, '123 Best Street');
Rec.Address := '234 Another Street';
Rec.Modify(true);
until Rec.Next() = 0;
This approach has several advantages:
- Field validation is respected — You can call
Validateon fields that need theirOnValidatetrigger to fire. - Single loop, single modify per record — Much more efficient than multiple
ModifyAllcalls. - Better readability — You can clearly see the filters being applied, the fields being changed, and the logic involved.
Here’s the complete example from the video, showing both approaches side by side:
pageextension 50100 VEndorListExt extends "Vendor List"
{
trigger OnOpenPage()
begin
// Approach 1: Two ModifyAll calls — loops twice, no field validation
Rec.ModifyAll(Name, '123 Best Street', true);
Rec.ModifyAll(Address, '234 Another Steet', true);
// Approach 2: Single loop — efficient, with validation control
Rec.SetRange();
Rec.SetFilter();
if Rec.FindSet(true) then
repeat
Rec.Validate(Name, '123 Best Street');
Rec.Address := '234 Another Steet';
Rec.Modify(true);
until Rec.Next() = 0;
end;
}
Why Erik Rarely Uses ModifyAll
Erik admits he very rarely uses ModifyAll in practice. His reasons are both technical and about code readability:
- It does too much in a single line. A
ModifyAllcall silently iterates over all filtered records and modifies them. When scanning code — like scanning a chess board to understand the position —ModifyAlldoesn’t make its impact visually obvious. - Filters are easy to miss. With a
FindSetloop, you can clearly seeSetRangeandSetFiltercalls that define which records are affected. WithModifyAll, the filters may have been applied many lines earlier, making it harder to reason about what’s being changed. - No field validation. For most real-world scenarios, you need field-level validation logic to run, which
ModifyAllsimply cannot do.
When ModifyAll Makes Sense
Erik acknowledges that ModifyAll does have legitimate use cases. It was originally designed for scenarios like clearing a single field on all lines of a sales document — simple, targeted operations where:
- Only one field needs to change
- No field validation logic needs to fire
- The operation is straightforward and well-understood
For these cases, ModifyAll is concise and effective. But as soon as you need to modify multiple fields, need validation logic, or want clear code readability, a FindSet loop is the better choice.
Summary
ModifyAll is a convenient but deceptive function in AL. The two key things to remember are: it never fires field OnValidate triggers (only the record’s OnModify trigger when RunTrigger is true), and calling it multiple times for different fields results in multiple full loops through the record set. In most cases, you’re better served by writing an explicit FindSet loop where you control validation, modify each record once, and keep your code readable and maintainable.