AfterDelete.PriorParentQuery
Reads fields of the record a lookup pointed to before the delete, such as a contact's former account, without SOQL in your handler. For the Id alone you do not need it: the old row still holds the lookup.
Interface
apex
public class AfterDelete {
public interface PriorParentQuery {
Map<SObjectField, TriggerHandler.ParentFields> queryParentsOnAfterDelete();
}
}queryParentsOnAfterDelete(): 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 ContactWriter implements AfterDelete.Writer, AfterDelete.PriorParentQuery {
public Map<SObjectField, TriggerHandler.ParentFields> queryParentsOnAfterDelete() {
return new Map<SObjectField, TriggerHandler.ParentFields>{ Contact.AccountId => TriggerHandler.ParentFields.with(Account.Name) };
}
public Boolean writeOnAfterDeleteWhen(TriggerHandler.DeleteRecord record) {
return record.getOldParent('Account') != null;
}
public void writeOnAfterDelete(TriggerHandler.DeleteRecord record, TriggerHandler.UnitOfWork unitOfWork) {
Account previousAccount = (Account) record.getOldParent('Account');
unitOfWork.toInsert(new Task(WhatId = previousAccount.Id, Subject = 'Contact left ' + previousAccount.Name));
}
}Good to Know
- Read by relationship name. Use
getOldParent('Account')forAccountId. The name is case-sensitive. - Read as it is now. The parent is queried when the trigger runs, so its fields show current values. It is null when the lookup was empty or the parent no longer exists.
- Only declared fields. The parent holds the declared fields and its
Id. Reading any other field throws anSObjectException. - Costs SOQL even when nothing qualifies. Each declared lookup costs one query per chunk, before any predicate runs.
- No sharing. Parents are read in system mode, so a handler can see records the user cannot.
