+ Start a Discussion
aquelleraqueller 

Avoiding recursive triggers

I need help with the following:

 

I have a trigger on a record update. The record is uploaded with the owner being 'admin'.

I want to change it to the true owner of the account:

 

trigger ChangeOwner on Opportunity(before update)
{
   // Create a list of Opportunities, newOpps, to make it bulk fiendly
   List<Opportunity> newOpps = new List<Opportunity>();

   for(Opportunity o : Trigger.new)
   {
      if(o.ForecastCategoryName == 'Closed')
      {
         // This query retrieves the account associated with the Opportunity
         Account myAcct = [select id, name, AccountNumber, owner from account where id = :o.AccountId];


         // Change owner

         o.OwnerId = myAcct.owner;

 

         update o;

 

   }

}

 

This code returns an (understandable) error that it contains illegal recursion.

 

How can I get around this problem and change a field just before the record is updated?

 

      Thx,

 

            aqueller

 

Best Answer chosen by Admin (Salesforce Developers) 
Rahul SharmaRahul Sharma

Hi aqueller, 

 

As you are already using before update trigger, you dont have to Update the opportunities again.

There were two problems in the code,

1) Query inside a for Loop.

2) Opportunity update in before update trigger on Oppotunity.

 

So, i have updated the code for you. check if it works.

 

trigger ChangeOwner on Opportunity (before update) 
{
    Set<Id> setAccountId = new Set<Id>();
    for(Opportunity o: Trigger.new)
        setAccountId.add(o.AccountId);
    Map<Id, Account> mapAccount = new Map<Id, Account>([Select Id, OwnerId from Account where Id in: setAccountId]);
    for(Opportunity o: Trigger.new)
        if(o.ForecastCategoryName == 'Closed')
            o.OwnerId = mapAccount.get(o.AccountId).OwnerId;
}

 

 

All Answers

apex_keenapex_keen

I didn't came accross the issue while performing such update .only thing is I didn't use 'if' conditional statement.

Although, an error do comes, but it was because you're( or me)  using ' update o;' statement which is not required, when using 'before update' trigger. 

raseshtcsraseshtcs

This can be done using workflow rules instead of trigger. It is always better to use workflow rules instead of trigger if you can.

Rahul SharmaRahul Sharma

Hi aqueller, 

 

As you are already using before update trigger, you dont have to Update the opportunities again.

There were two problems in the code,

1) Query inside a for Loop.

2) Opportunity update in before update trigger on Oppotunity.

 

So, i have updated the code for you. check if it works.

 

trigger ChangeOwner on Opportunity (before update) 
{
    Set<Id> setAccountId = new Set<Id>();
    for(Opportunity o: Trigger.new)
        setAccountId.add(o.AccountId);
    Map<Id, Account> mapAccount = new Map<Id, Account>([Select Id, OwnerId from Account where Id in: setAccountId]);
    for(Opportunity o: Trigger.new)
        if(o.ForecastCategoryName == 'Closed')
            o.OwnerId = mapAccount.get(o.AccountId).OwnerId;
}

 

 

This was selected as the best answer
aquelleraqueller

Hello Rahul,

 

Your suggested implementation works very well.

I have never used Map, but given your example, I found it to be very useful.

 

        Thank you very much.

 

                  aqueller

aquelleraqueller

I tried it, but a workflow rule allows me to changes the owner to a particular name, but doesn't allow me to assign it programmatically to the owner of the account.

 

Is there another way of using workflow rules?

 

      Thanks,

 

             aqueller

aquelleraqueller

Hi,

 

I tried it without the 'update' and indeed it works correctly.

 

        Best Regards,

 

                   aqueller

Rahul SharmaRahul Sharma

Yup, with removing "update" from your previous code will work.

but if you go for bulk update the records (using dataloader) then, it will hit governor limits and cause exception.

So always write trigger which would be bulk enabled.