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')forAccountIdandgetOldParent('Parent')forParentId. 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 anSObjectException. 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.
