Skip to content

BeforeDelete.PriorParentQuery

Reads fields of the record a lookup points to, such as a deleted contact's account, without SOQL in your handler. The row being deleted holds only the lookup Id.

Interface

apex
public class BeforeDelete {
    public interface PriorParentQuery {
        Map<SObjectField, TriggerHandler.ParentFields> queryParentsOnBeforeDelete();
    }
}
  • queryParentsOnBeforeDelete(): called once per chunk, before the first handler runs; not called for a bypassed handler. Returns lookup field → the parent fields to load.

In delete contexts the PriorParentQuery method is named queryParentsOn<Ctx>().

Example

apex
public with sharing class ContactHandler implements BeforeDelete.Handler, BeforeDelete.PriorParentQuery {
    public Map<SObjectField, TriggerHandler.ParentFields> queryParentsOnBeforeDelete() {
        return new Map<SObjectField, TriggerHandler.ParentFields>{ Contact.AccountId => TriggerHandler.ParentFields.with(Account.Name) };
    }

    public Boolean qualifiesForBeforeDeleteWhen(TriggerHandler.DeleteRecord record) {
        return record.getOldParent('Account') != null;
    }

    public void onBeforeDelete(TriggerHandler.DeleteRecord record) {
        record.getOldSObject().addError('Remove the contact from ' + ((Account) record.getOldParent('Account')).Name + ' before you delete it.');
    }
}

Good to Know

  • Read by relationship name. Use getOldParent('Account') for AccountId and getOldParent('Parent') for ParentId. The name is case-sensitive.
  • Check for null. The parent is null when the lookup is empty or no record has that Id.
  • Only declared fields. The parent holds the declared fields and its Id. Reading any other field throws an SObjectException. Add grandparent fields with .with('Owner', User.IsActive).
  • One query per lookup. Each declared lookup costs at most one SOQL query per chunk, even when no record qualifies.
  • No sharing. Parents are read in system mode, so a handler can see records the user cannot.