+ Start a Discussion
Kumar Rao 1Kumar Rao 1 

Trigger - After Update

Dear Folks,

I would like to update a record, after it's inserted. but I encountered bellow error.. Please help me.

Error: Parthiv.Product: execution of AfterUpdate caused by: System.FinalException: Record is read-only: Class.Parthiv.PromoProd.Crnt_Status: line 10, column 1

Trigger:
trigger Product on Parthiv__PromoProduct__c (after insert, after update) {

if(Trigger.isAfter){
    if(Trigger.isupdate){
        PromoProd.Crnt_Status(Trigger.old);        
      }
    }
}

-------------------------------------------------------------------------------------------------------------------------------------
Class:

public with sharing class PromoProd {
    
//Product current Status Update based on New Status
    public static void Crnt_Status(list<Parthiv__PromoProduct__c>PP){
        
        list<Parthiv__PromoProduct__c> p = new list<Parthiv__PromoProduct__c>();

        
        for(Parthiv__PromoProduct__c prod:pp){
            prod.Parthiv__Cur_Status__c = prod.Parthiv__New_Status__c;
            p.add(prod);
        } update p;
    }    

}
Best Answer chosen by Kumar Rao 1
Ketankumar PatelKetankumar Patel
Hi Kumar, 

In after update or after insert call you cannot call DML to trigger.new or trigger.old. At that time they are read-only. You should use List or Map and store values in it and then update that List or Map values at end of your trigger.

Once you do that you could also face recursion issue. if you trying to update same object records.

And why do you use Trigger.old values for update call? You should use Trigger.new. 

The only use case I know to use trigger.old is to compare it fields with Trigger.New fields to check where there is a change or not to a particular field and apply some kind of logic based on the comparison. 
trigger Product on Parthiv__PromoProduct__c (after insert, after update) {
List<Parthiv__PromoProduct__c> pList = new list<Parthiv__PromoProduct__c>();
if(checkRecursive.runOnce()){
if(Trigger.isAfter){
	//write your code here            
		if(Trigger.isupdate){
			pList = PromoProd.Crnt_Status(Trigger.New);        
		}
    }
  }
  Update pList;
}
 
public with sharing class PromoProd {
    
//Product current Status Update based on New Status
    public static List<Parthiv__PromoProduct__c> Crnt_Status(list<Parthiv__PromoProduct__c> PP){
        
        list<Parthiv__PromoProduct__c> p = new list<Parthiv__PromoProduct__c>();
        for(Parthiv__PromoProduct__c prod:pp){
            prod.Parthiv__Cur_Status__c = prod.Parthiv__New_Status__c;
            p.add(prod);
        } return p;
    }    
}
 
public Class checkRecursive{
    private static boolean run = true;
    public static boolean runOnce(){
    if(run){
     run=false;
     return true;
    }else{
        return run;
    }
    }
}

All Answers

Pramodh KumarPramodh Kumar
trigger Product on Parthiv__PromoProduct__c (after insert, after update) {
list<productIds> updateProduct = new list<productIds>();
list<id> productIds = new list<id>();
    if(Trigger.isupdate){
        for(Parthiv__PromoProduct__c pp : trigger.old)
                 productIds(pp.id);        
      }
          for(Parthiv__PromoProduct__c pp : [select id from Parthiv__PromoProduct__c where                                               id IN: productIds]){
          pp.prod.Parthiv__Cur_Status__c = pp.Parthiv__New_Status__c;
         
updateProduct.add(pp);

         }
  update updateProduct;
 
}
Thanks,
pRAMODH.
Ketankumar PatelKetankumar Patel
Hi Kumar, 

In after update or after insert call you cannot call DML to trigger.new or trigger.old. At that time they are read-only. You should use List or Map and store values in it and then update that List or Map values at end of your trigger.

Once you do that you could also face recursion issue. if you trying to update same object records.

And why do you use Trigger.old values for update call? You should use Trigger.new. 

The only use case I know to use trigger.old is to compare it fields with Trigger.New fields to check where there is a change or not to a particular field and apply some kind of logic based on the comparison. 
trigger Product on Parthiv__PromoProduct__c (after insert, after update) {
List<Parthiv__PromoProduct__c> pList = new list<Parthiv__PromoProduct__c>();
if(checkRecursive.runOnce()){
if(Trigger.isAfter){
	//write your code here            
		if(Trigger.isupdate){
			pList = PromoProd.Crnt_Status(Trigger.New);        
		}
    }
  }
  Update pList;
}
 
public with sharing class PromoProd {
    
//Product current Status Update based on New Status
    public static List<Parthiv__PromoProduct__c> Crnt_Status(list<Parthiv__PromoProduct__c> PP){
        
        list<Parthiv__PromoProduct__c> p = new list<Parthiv__PromoProduct__c>();
        for(Parthiv__PromoProduct__c prod:pp){
            prod.Parthiv__Cur_Status__c = prod.Parthiv__New_Status__c;
            p.add(prod);
        } return p;
    }    
}
 
public Class checkRecursive{
    private static boolean run = true;
    public static boolean runOnce(){
    if(run){
     run=false;
     return true;
    }else{
        return run;
    }
    }
}
This was selected as the best answer
Kumar Rao 1Kumar Rao 1
Thanks Pramodh and Ketan, your both answers helped me to understand much better. Thanks for your help again.