Read a Contact's Account
Query the org (SOQL) · Intermediate · 14 min · Runs in your Salesforce Developer org · Apex Path
Scenario. A Contact export needs the parent Account name but must also survive Contacts that are not linked.
Read Account.Name through each tagged Contact, and use it safely for a Contact that has no Account.
What you will learn
A child-to-parent query uses dot notation. From Contact, select Account.Name, then read it from each row.
for (Contact row : [SELECT Id, Account.Name FROM Contact]) {
String parentName = row.Account?.Name;
}
?. is safe navigation: it gives null when row.Account is null.
Gotcha. Reading row.Account.Name on a Contact with no Account returns null without throwing — but calling .toUpperCase() on that null does throw. Check for null first.
The task
Query three tagged Contacts, read each one's Account name through the relationship, and upper-case it without crashing on the Contact that has no Account.
Examples:
- two Contacts with an AccountId →
Contacts with an Account: 2 - both upper-cased parent names equal the seeded Account's upper-cased Name →
Parent names match: true - one Contact with no Account →
Contacts without an Account: 1andOrphan parent name: null, with no error
Requirements:
- Query Contacts with
LastName LIKE :contactPattern, and selectAccount.Name. - Loop over the rows. Read the parent name with
row.Account?.Name. Reading it never throws. For the Contact with no Account you get null. - When the parent name is not null, upper-case it with
toUpperCase()and compare it withparent.Name.toUpperCase(). That call is what throws on a null. StartparentNamesMatchastruebefore the loop and set it tofalsewhen a name differs. - Count Contacts with and without an Account. For the Contact with no Account, store its parent name (null) in
orphanParentName. - Print
Contacts with an Account:,Parent names match:,Contacts without an Account:andOrphan parent name:.
Starter code
String tag = 'AS-Q306-' + UserInfo.getUserId() + '-' +
String.valueOf(Datetime.now().getTime());
Account parent = new Account(Name = tag);
insert parent;
List<Contact> seeded = new List<Contact>{
new Contact(LastName = tag + '-LinkedA', AccountId = parent.Id),
new Contact(LastName = tag + '-LinkedB', AccountId = parent.Id),
new Contact(LastName = tag + '-Orphan')
};
insert seeded;
String contactPattern = tag + '-%';
Integer linkedCount = 0;
Integer orphanCount = 0;
Boolean parentNamesMatch = true;
String orphanParentName = 'unknown';
System.debug('Contacts with an Account: ' + linkedCount);
System.debug('Parent names match: ' + parentNamesMatch);
System.debug('Contacts without an Account: ' + orphanCount);
System.debug('Orphan parent name: ' + orphanParentName);
When it passes
Two Contacts read and upper-case the seeded Account's Name, and the Contact with no Account is counted and reported as null without an error.
You write the Apex yourself. ApexSensei runs it and tells you what passed and what did not.