[SalesForce] Get values of the records from Trigger.NewMap in Before Update Triggers

I am writing a trigger on Account to update the phone number of all the contacts associated with it,with the phone number of that account. (I understand this is possible using Process builder, However I am trying to get some hands on Triggers).I have written a Before update trigger. Below is the logic.

public static void onBeforeUpdate( Map<Id,Account> newAccountMap)
{
   For(Contact c : [Select Id,AccountId from Contact where AccountId in : newAccountMap.keyset()])
   {
     c.Phone = newAccountMap.get(c.AccountId).Phone ; 
   }
}

When I update the phone on an account record from lets say XXXXX123 to XXXXX456,
all the contacts associated with it still have phone values as XXXXX123 AND NOT
XXXXX456
I looked into the official doc for trigger and it seems Trigger.New or Trigger.newMap values are still not yet committed to the database, hence value newAccountMap.get(c.AccountId).Phone returns the existing value in the database and not the new value. Neither we can get the new values of Phone on an
account using SOQL.My query is- How can we get New Values from the Trigger.newmap and update the corresponding contact record with the new value.?
It works fine with the below After Update trigger

public static void onAfterUpdate( Map<Id,Account> newAccountMap)
{   
   List<Contact> con = New List<Contact> ();
   For(Contact c : [Select Id,AccountId from Contact where AccountId in : newAccountMap.keyset()])
   {
     c.Phone = newAccountMap.get(c.AccountId).Phone ; 
     con.add(c);
   }
   update con;
}

But, I don't want to use After Insert , since I need to use DML as well in an After Insert , which will fire a trigger on contact (which I don't want)

Best Answer

You absolutely must fire an update on the related Contact records. If you just update fields in memory, the only way those changes will persist to the database is if you are setting fields on the records in trigger.new. It won't work for related records which you have queried.

Any cross-object logic should always occur in after triggers. See, for example:

Triggers

There are two types of triggers:

  • Before triggers are used to update or validate record values before they’re saved to the database.
  • After triggers are used to access field values that are set by the system (such as a record's Id or LastModifiedDate field), and to affect changes in other records, such as logging into an audit table or firing asynchronous events with a queue. The records that fire the after trigger are read-only.
Related Topic