2

I am writing a Trigger on Account object to capture and place the id in one field. Whenever the record is inserted or updated it should display the id of the record in ID_of_Record__c field on Account.

I have tried below code but giving error.

trigger CaptureID on Account (after insert, after update) {

    List<Account> acclst = new List<Account>();
    for(Account acc:Trigger.new)
    {
        acc.ID_of_Record__c = acc.Id;
        acclst.add(acc);
    }
    update acclst;
}
  • What error you are getting? – Ashwani Oct 15 '15 at 11:29
  • Apex trigger CaptureID caused an unexpected exception, contact your administrator: CaptureID: execution of AfterUpdate caused by: System.FinalException: Record is read-only: Trigger.CaptureID: line 6, column 1 – Prince Oct 15 '15 at 11:32
6

You can do it with Formula field and Workflow. Trigger is not required for this scenario.

Create formula field of type text and write ID in formula editor. Save the field.

OR

You can do it using workflow rule. Set field update action and update the field with record ID.

OR

With Trigger ( Bad code written in the cleanest way, less developers will curse :) )

trigger CaptureID on Account (after insert, before update) {

    List< Account > acclst = new List< Account >();
    for(Account acc:Trigger.new)
    { 
         if(Trigger.isAfter && Trigger.isInsert)
         {
           Account  accnew = new Account (Id = acc.Id);
           accnew. ID_of_Record__c = acc.Id;
           acclst.add(accnew);
         }
         else if(Trigger.isBefore && Trigger.isUpdate)
         {
             acc. ID_of_Record__c = acc.Id;
         }
    }
    if(Trigger.isAfter && Trigger.isInsert)
      update acclst;
}
  • yeah i know by formula field we can achieve easily. But am trying with trigger @Ashwani – Prince Oct 15 '15 at 11:35
  • 1
    Why would you do it with a trigger? Is this just an exercise to see if it can be done? If so, Trigger.new is read-only in the after cycle. If it is for production, then do yourself a favor. Don't use a trigger. Use a formula field. Or, use a workflow field update with a formula to copy the Id value into this field on insert. – pchittum Oct 15 '15 at 11:38
  • for future purposes am writing trigger. Tell me if there is any way to get id by Trigger. @Peter – Prince Oct 15 '15 at 11:41
  • @Prince Trigger way is also updated. – Ashwani Oct 15 '15 at 11:52
  • @Ashwani when inserting a new record only it is fetching record to the field but not with updation – Prince Oct 15 '15 at 11:59
1

Ok...I'll answer this with code, just for the sake of it. Consider this a kind of code-golf-with-triggers-in-apex answer.

But why would you do it when you can use a formula field?

In the docs it clearly states that in the after state, the sObject instances of Trigger.new are read-only. So what you are attempting (calling update on Trigger.new in an after trigger) will fail. The main reason for this is the fundamental problem of calling update on a record that has already been saved/inserted (but not committed) to the DB. Also there is the problem that calling update on a trigger with an update trigger on it creates a race condition where trigger triggers trigger, triggers trigger, ad nauseum, ad governor-limit-exceptium.

But again, why on earth would you bother when a formula field would work, take less time to implement, and not require test code.

That's not to say your trigger can't update the records in the after state...you just need a new instance to write to the DB. Then you need a static variable to stop the race condition.

There are many posts and many blogs on how to avoid trigger race conditions. Using a static variable. Using a more advanced structure. So look closely at that. I'm not going to waste space here to repeat those examples.

As far as getting the accounts to save, you need to create a list of new Account instances to work with...not just pass the reference to the ones in Trigger.new.

List<Account> listOfAccountsToUpdate = new List<Account>();
for (Account a : Trigger.new){
  //creating the new account instance is key. this decouples the record
  //in the DB from the R.O. instance sitting in trigger.new
  Account newAccountInstance = new Account(Id=a.Id);
  newAccountInstance.ID_of_Record__c = a.Id;
  listOfAccountsToUpdate.add(newAccountInstance);
}
update listOfAccountsToUpdate;

Of course, you're going to do this as a formula field in production anyway, so this really is pointless, right?

One final thing...

You can actually skip the possibility of recursion by not making this an update trigger. If all you are doing is copying from Id to your custom field, update is superfluous. Id is not updateable. Yep, the system will never update that Id value, so take out the after update and you remove a lot of potential pain for yourself, future developers, and your users.

But I don't want you to vote for my answer. So please, please, pretty please, don't check it as correct. Check formula field answer as the correct one.

0

ok after @Peter, @Ashwani suggestions and codes. I got my answer Here for updation I used Recursvice class with recursive class

Recursive Class

public class RecursiveClsForCaptureIDTrigger {

     private static boolean run = true;
     public static boolean runOnce(){
       if(run)
       {
         run=false;
         return true;
       }
       else
       {
        return run;
       }
    }
}

Trigger for update and insert

trigger CaptureID on Account (after insert, after update) {

    List<Account> acclst = new List<Account>();
    for(Account acc:Trigger.new)
    { 
         Account  accnew = new Account (Id = acc.Id);
         accnew.ID_of_Record__c = acc.Id;
         acclst.add(accnew);
    }
    if(Trigger.isAfter && Trigger.isInsert){
        update acclst;
    }      
    if(Trigger.isAfter && Trigger.isUpdate){
        if(RecursiveClsForCaptureIDTrigger.runOnce())
        {
            update acclst;
        }
    }

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.