| bc-version |
domain |
keywords |
technologies |
countries |
application-area |
|
|
performance |
| event-subscriber |
| guard |
| db-call |
| frequently-fired |
| validate |
|
|
|
|
Guard event subscribers with cheap checks before any database call
Description
Event subscribers fire on every event matching their signature — for OnAfterValidateEvent on a hot field like Sales Line.Quantity, that is every quantity edit by every user. Per the upstream guidance, "Keep event subscriber code lightweight" and "Avoid database operations in frequently-fired events — guard with cheap checks first." A Get or FindFirst at the top of such a subscriber pays a database round-trip on every fire, including the calls for which the subscriber's work was not needed.
Best Practice
Open the subscriber with an in-memory predicate that filters out the calls the subscriber does not handle — record type, document type, status, parameter-passed flags. Only after the cheap guard passes should the body issue a database call, and only with SetLoadFields for the columns the body actually reads.
See sample: guard-event-subscribers-before-db-call.good.al.
Anti Pattern
[EventSubscriber(...'OnAfterValidateEvent', 'Quantity', ...)] local procedure ... var Item: Record Item; begin Item.Get(Rec."No."); if Item.HasCustomPricing() then ...; — Item.Get runs on every quantity change, including changes to lines whose Type is not Item. A pre-check if Rec.Type <> Rec.Type::Item then exit; ahead of the Get removes most of the calls.
See sample: guard-event-subscribers-before-db-call.bad.al.