function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
SalesForce DummySalesForce Dummy 

Trigger question

OK I'm pulling my hair out. I'm trying to access a field from the account object after a contact is inserted. Here's the generic code:

 

trigger contactTest on Contact(after Insert)
{
 //Create list and set
 List<Contact> listContact = new List<Contact>();
 Set<Id> setContact = new Set<Id>();

 //Loop through trigger items
 For(Contact loopContact : Trigger.new)
 {
  //Create new contact for updating
  Contact newContact = new Contact(Id = loopContact.Id);

  //Get field from Account
  newContact.FieldFromAccount = loopContact.Account.FieldFromAccount;
  
  //Make sure distinct list of contacts
  if(!(setContact.contains(loopContact.Id))
  {
   listContact.add(newContact);
   setContact.add(newContact.Id);
  }
 }

 //Update list of Contacts
 update listContact;
}

 

The field comes up as null even though it's populated. It's a checkbox. What am I doing wrong?

Best Answer chosen by Admin (Salesforce Developers) 
kibitzerkibitzer

What a curious design pattern. I've never seen anyone try to update contacts like that before - creating a new one and setting the ID then doing an update. It seems unlikely that would work. You can just update the objects directly and then call update - you don't need to create a new Contact object.

 

Anyway, in terms of loopContact.Account.FieldFromAccount being null - that's an easy one. A trigger does not populate the entire object relationship tree.

 

What you need to do is loop through the contacts and grab a Set of AccountIDs that are used by the contacts.

 

Then use a SOQL query to retreive the fields - something like

Map<ID, Account> accounts = new Map<ID, Account>([SELECT ID, FieldFromAccount from Account where ID in :setofaccountids]);

 

Then you do the assignment, something like this:

 

List<Contact> contactstoupdate = new List<Contact>();

For(Contact loopContact : Trigger.new)
 {
    if(loopContact.AccountID!=null){

        loopContact.FieldFromAccount = accounts.get(loopContact.AccountID).FieldFromAccount;

        contactstoupdate.add(loopContact);

        }

}

 

update contactstoupdate;

 

As you see - no need to create a new contact. Accounts aren't required for contact, so you need to test for a valid AccountID both here, and when you create the Set of AccountIDs earlier.

 

This code is not tested - so there may be typos or syntax errors, but the approach is sounds.

 

Good luck


Dan

 

All Answers

kibitzerkibitzer

What a curious design pattern. I've never seen anyone try to update contacts like that before - creating a new one and setting the ID then doing an update. It seems unlikely that would work. You can just update the objects directly and then call update - you don't need to create a new Contact object.

 

Anyway, in terms of loopContact.Account.FieldFromAccount being null - that's an easy one. A trigger does not populate the entire object relationship tree.

 

What you need to do is loop through the contacts and grab a Set of AccountIDs that are used by the contacts.

 

Then use a SOQL query to retreive the fields - something like

Map<ID, Account> accounts = new Map<ID, Account>([SELECT ID, FieldFromAccount from Account where ID in :setofaccountids]);

 

Then you do the assignment, something like this:

 

List<Contact> contactstoupdate = new List<Contact>();

For(Contact loopContact : Trigger.new)
 {
    if(loopContact.AccountID!=null){

        loopContact.FieldFromAccount = accounts.get(loopContact.AccountID).FieldFromAccount;

        contactstoupdate.add(loopContact);

        }

}

 

update contactstoupdate;

 

As you see - no need to create a new contact. Accounts aren't required for contact, so you need to test for a valid AccountID both here, and when you create the Set of AccountIDs earlier.

 

This code is not tested - so there may be typos or syntax errors, but the approach is sounds.

 

Good luck


Dan

 

This was selected as the best answer
SalesForce DummySalesForce Dummy

Awesome. Thanks, Kibitzer!!