+ Start a Discussion
Andrea IanniAndrea Ianni 

Trigger before and after insert

trigger theNameGioele on Contact (before insert, after insert) {

    for (Contact cont: Trigger.new){
        if(cont.firstname == 'Gioele'){
            cont.Description = 'This guy has my son name!';
        }    
    }
   
}
Look at this very easy example.

Behaviour I expected: when I insert "Gioele Ianni" in SF the system change the Description of the record, before the insert. Then it overwrite the field Description with the same statement, after the insert.

Real behaviour: Error: Invalid Data. 
Review all error messages below to correct your data.
Apex trigger theNameGioele caused an unexpected exception, contact your administrator: theNameGioele: execution of AfterInsert caused by: System.FinalException: Record is read-only: Trigger.theNameGioele: line 5, column 1


Obviously everything works if I remove the "after insert".



 
Best Answer chosen by Andrea Ianni
ManojjenaManojjena
HI Andrea,

Please try below code 
trigger theNameGioele on Contact (before insert,after insert) {
   Set<Id> idSet=new Set<Id>();
   if(Trigger.isBefore){
		for (Contact cont: Trigger.new){
			if(cont.firstname == 'Gioele'){
				cont.Description = 'This guy has my son name!';
			}    
		}
   }if(trigger.isAfter){
     for (Contact cont: Trigger.new){
	   idSet.add(cont.Id);
	 }
	 List<Contact> conListToUpdate =new List<Contact>();
	 For(Contact con:[SELECT id FROM Contact WHERE Id IN : idSet AND firstname = 'Gioele']){
	   con.Description = 'This guy has my son name!';
	   conListToUpdate.add(con);
	 }
	 try{
	   update conListToUpdate;
	 }catch(DmlException de ){
	   System.debug(de);
	 }
   }
   
}

 

All Answers

SantoshChitalkarSantoshChitalkar
What is your question if you already knew that removal of 'After insert' will solve your problem??

 
ManojjenaManojjena
HI Andrea,

Please try below code 
trigger theNameGioele on Contact (before insert,after insert) {
   Set<Id> idSet=new Set<Id>();
   if(Trigger.isBefore){
		for (Contact cont: Trigger.new){
			if(cont.firstname == 'Gioele'){
				cont.Description = 'This guy has my son name!';
			}    
		}
   }if(trigger.isAfter){
     for (Contact cont: Trigger.new){
	   idSet.add(cont.Id);
	 }
	 List<Contact> conListToUpdate =new List<Contact>();
	 For(Contact con:[SELECT id FROM Contact WHERE Id IN : idSet AND firstname = 'Gioele']){
	   con.Description = 'This guy has my son name!';
	   conListToUpdate.add(con);
	 }
	 try{
	   update conListToUpdate;
	 }catch(DmlException de ){
	   System.debug(de);
	 }
   }
   
}

 
This was selected as the best answer
AshlekhAshlekh

Hi Andrea,

Whenever a record is going to save then according to salesforce document and excuation order. Before trigger will fire first and after saving the record in database then after trigger will fire.

In before trigger you can change the value of record which is going to insert. But in after trigger the record is locked and no body can change any things related to that record. 

So you have to put condition in your code, which is already provided by "Manoj Kumar jena" snippet.

Here are two links where you can study more about trigger contexts.

https://www.salesforce.com/us/developer/docs/apexcode/Content/apex_triggers.htm
https://www.salesforce.com/us/developer/docs/apexcode/Content/apex_triggers_context_variables.htm

Blog:  https://jonyforce.wordpress.com/2015/04/02/apex-trigger/

 

Please mark as solution if this information help you. Enjoy life and Enjoy Apex. 

AnjaneyluAnjaneylu
Hi Manojj kumar,
i have one doubt inyour code, that is you have written SOQL Query inside for loop..
normally if we write the soql queries inside for loop, then easiy our code hit the governer imits. Then is it suggestable to write soql inside  for loop..
Thanks and regards,
anji
 
ManojjenaManojjena
Hi Anji ,

This is not query inside for loop ,In sales force this called as SOQL for Loop .
If you will write query inside for loop and execute the code in limit you will see the query count 
Please check below link .
https://www.salesforce.com/us/developer/docs/apexcode/Content/langCon_apex_loops_for_SOQL.htm

1.For(Account acc : [Select id ,Name From Account ]){

}
2.For(Contact con :Trigger.New ){
  Account acc=[Select Id From Account WHERE id =: con.AccountId];
}

If you have any doubt please ask question with different post it will be help full  to others as well .
Please let me know still if you have any doubt .
SantoshChitalkarSantoshChitalkar
Yes, Anji. The way Manoj wrote the code, it is not considered in loop.
AnjaneyluAnjaneylu
Thanks Manoj and Santosh. 
Now i  got the Clarity..
Thanks,
Anji