Categories
Business Central Development

When xRec doesn’t Work!

The Business Central ‘xRec’ and ‘Rec’ records available when you subscribe to database record changes don’t always work! Here’s a simple work-around

There appears to be a longstanding bug (undocumented feature) in Business Central, which may have been around since the old CAL days, and still appears in the v15+ AL code.

It’s all around Rec and xRec – which are the very useful records you get passed to you when subscribing to events/triggers on data changing in tables.

The code below shows I’m subscribing to modifications in a table, in the OnBeforeModifyEvent. I am not limiting it to any columns, as my code needs to compare quite a few columns to see if they have changed, and if so, I record to a new log table, so I can pick them up and process in a scheduled job entry task.

/*  Item changes */
    [EventSubscriber(ObjectType::Table, Database::"IC Items M04", 'OnBeforeModifyEvent', '', false, false)]
    local procedure ItemOnBeforeModify(var Rec: Record "IC Items M04"; var xRec: Record "IC Items M04")
    var
        StatusChangeType: Enum "Status Change Type";
        CompareRec: Record "IC Items M04";
    begin

// if a temporary record, or if item doesn't really exist in the DB ignore
        if Rec.IsTemporary then
            exit;

        // only replicate if data changed in SDL or FL companies. ignore SIL / R2R / Prod Maint!
        if not ((Rec.CurrentCompany.StartsWith('SDL') OR Rec.CurrentCompany.StartsWith('FL'))) then
            exit;

        // try and get around a bug where xRec doesn't contain original values if changed via CODE and not edited on a screen!
        CompareRec.Reset();
        CompareRec.SetRange("Item No.", Rec."Item No.");
        if CompareRec.FindFirst() then begin

            if (Rec.Closed <> CompareRec.Closed) then begin
                logItemChange(Rec, StatusChangeType::Closed);
            end;

The xRec values SHOULD be filled with the “pre-change” values of the fields, that’s the whole point of the xRec, and the Rec record should hold the values “post-change”. The documentation on the Microsoft website tell you this.

What it doesn’t mention, is that the xRec record only sets set correctly IF THE EDIT WAS MADE BY A USER IN A SCREEN. If values change in the target table due to a CodeUnit updating view an action, the xRec doesn’t hold the old values, so any comparisons to Rec show no change!

In a forum post we saw reporting this bug, it appears Microsoft themselves cannot fix this “bug” – as it will break other functionality, so it’s being left as is.

My code above gets around the fact you cannot trust xRec content by going back to the database and reloading the original data into a new Record, then comparing Rec against that (CompareRec). It’s a simple fix, but shouldn’t be needed, and was very frustrating as much of our testing showed the comparisons would work between Rec and xRec, because I was editing fields in screens – not running a process to change the values.

By Krispy Brown

Developer (Java / PHP / MS Business Central AL).
Beer brewer and drinker.
DIY Punk promoter.