function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Manjunath reddy 25Manjunath reddy 25 

Can we use DML operations in before triggers?

Hi both the below triggers wotks fine , I have a question here , in my first trigger posted below I am using DML update accs.values();,If I remove DML trigger doesn't work, in my second trigger If I use DML update contactListToUpdate;, iam getting error

 "Error: Apex trigger ownerChange caused an unexpected exception, contact your administrator: ownerChange: execution of BeforeUpdate

caused by: System.DmlException: Update failed. First exception on row 0 with id 0039000001yu7JUAAY; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, changeOwner: execution of AfterUpdate

caused by: System.DmlException: Update failed. First exception on row 0 with id 0019000001i0umdAAA; first error: SELF_REFERENCE_FROM_TRIGGER, Object (id = 0019000001i0umd) is currently in trigger ownerChange, therefore it cannot recursively update itself: []

(): []: ()"


Now Iam confused whether we can use DML operations in before triggers or not.Can some explain me if we can use DML operations in before triggers
trigger ownerChange on Account (before insert, before update) {
    List<id> accountIdsList = new list<id>();
    list<contact> contactListToUpdate = new list<contact>();
    for(account acc : trigger.new){
        accountIdsList.add(acc.id);
    }
    
    list<contact> contactList = [select id from contact where accountId IN:accountIdsList ];
    
    for(account acc : trigger.new){
        if(acc.ownerId!=trigger.oldMap.get(acc.id).ownerId){
         for(contact con : contactList){
             con.ownerId = acc.ownerId;
             contactListToUpdate.add(con);
         }    
        
        }
        update contactListToUpdate;
    }
    
    
}

?
/ The trigger needs to check all the other Opportunities related to the Account of the Opportunity being updated. It should check to see if any of the Opportunities have a StageName equal to 'Closed Won ',
// if so, it should update the account Type to 'Customer'. If none of the Opportunities are closed won, the Account Type should be 'Prospect
trigger updateAccountIfOppCustomer on Opportunity (before insert, before update) {
    list<opportunity> accOpps = new list<opportunity>();
    list<id>  accountIds = new list<id>();
    
    for(opportunity opp:trigger.new){
        accountIds.add(opp.accountId);
    }
    
    list<opportunity> opps = [select id,AccountId,StageName  from opportunity where accountId IN:accountIds];
    map<id,account> accs = new map<id,account>([select id,type from account where id IN:accountIds]);
    system.debug('accs '+accs );
    for(opportunity o:opps){
            if (o.StageName == 'Closed Won'  || o.StageName == 'Customer Reseller') {
                //acc.type = 'prospect';
                accs.get(o.accountId).type='prospect';
        }
    }
    
    update accs.values();
    
}

 
SandhyaSandhya (Salesforce Developers) 
Hi,

Please see below code.
trigger ownerChange on Account (before insert, before update) {
     System.debug('ownermid');

    List<id> accountIdsList = new list<id>();
    list<contact> contactListToUpdate = new list<contact>();
    for(account acc1 : trigger.new){
        accountIdsList.add(acc1.id);
    }
    list<Account> AccountList= new list<Account>();
     AccountList = [select id,ownerId from Account where Id IN:accountIdsList ];
    System.debug('ownermid' +AccountList);
           list<contact> contactList = [select id from contact where accountId IN:accountIdsList ];     

    for(account acc :AccountList){

        if(acc.ownerId!=trigger.oldMap.get(acc.id).ownerId){
        
        for(contact con : contactList){

             con.ownerId = acc.ownerId;

             contactListToUpdate.add(con);
         }  
                    
         }    
              
        update contactListToUpdate;
    
   } 
    
}

Hope this helps you!

Thanks and Regards
Sandhya
sandeep reddy 37sandeep reddy 37
yes we can do
trigger insertacc on account(before insert){

for(account a:trigger.new){
if(a.industry=='banking){'
​conatac c=new contact();
c.lastname=a.name;
insert c;
}
}
Manjunath reddy 25Manjunath reddy 25
Hi Sandhya and sandeep ,

My triggers above posted are working fine,provided I use update accs.values(); Line number  18 in the above trigger, and in the other trigger I should remove  update contactListToUpdate; line number 27 then it works fine,my question is why does it behaves like that, whether we have to use DML or not in before triggers, Please let me know.
Niranjan Jadhav 7Niranjan Jadhav 7

Hi Manjnath,

Values which you are already updating in the trigger can't be updated through a DML in the trigger again, it will give "Self_reference error".

 

Thanks & Regards

Niranjan Jadhav

Pratap GaraniPratap Garani
Hi Manju,
Just apply a bit of sense from your side then it will be quite easy for you to decipher the reason behind the nature you asked for.
Look in before insert trigger you cannot update the original object using a DML operation. 
You might ask that you are trying your DML operation on Contact but not on Account which is your orginal object in your 1st scenario. The reason you are getting the error because In before insert trigger you cannot update the original object using a DML operation also means that nothing can reference the original object also nothing can update it.

Now see your line no. 11 in the 1st scenario you are referring to the Id of the account which sadly is not yet committed to your database in a before insert trigger. I hope this will clear the fog around your first scenario.

Now try applying sense on the second one and I am sure you will be able to answer your query by yourself. If not I will be happy to help :)