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
LloydSilverLloydSilver 

How do I move the update DML outside the loop

Just learning APEX so appreciate the help.

 

I've created a trigger on a custom object. When the child object (Carrier_Contract__c) is inserted or updated, and the custom field "Has_Paid_For_A_Case__c" is true, it should check the single contact record associated with the record (Agent__c) and if that record's custom field Has_Paid_For_A_Case__c (different than the one on the trigger) is unchecked, go ahead and check it (true).

 

It should work but as it stands the update happens inside the loop which could cause an issue. 

 

How do I move the update outside the loop. And if there's anything else I'm doing wrong I'd certainly appreciate hearing about that as well.

 

Thanks.

trigger UpdateContactHasPaidForCase on Carrier_Contract__c (after insert, after update) {
	
	List<String> contractNames = new List<String>{};
	
	for(Carrier_Contract__c contract: Trigger.new){
	
		if(contract.Has_Paid_For_A_Case__c == TRUE && contract.RecordTypeID == '012i0000000FAWI'){
		
			Contact con = [select ID, Has_Paid_For_A_Case__c from Contact where ID = :contract.Agent__c];
		
			if(con.Has_Paid_For_A_Case__c == FALSE){
			con.Has_Paid_For_A_Case__c = TRUE;
			update con;
			}
			
		}
		
	}
	

}

 

k_bentsenk_bentsen

General best practice is to create an empty list of the object you plan to update and as you iterate and find records that need to be updated, you make the changes then add that record to that list. After your looping is done, you do an "update" on that list. Even if you've added 50 records to the list, the system only considers it a single DML operation. In addition to DML, you want to have your SOQL query outside of the loop. I've modified your code below to account for both changes, hopefully you can understand what's going on with what I changed.

 

trigger UpdateContactHasPaidForCase on Carrier_Contract__c (after insert, after update) {
    
    List<String> contractNames = new List<String>{};
    List<Id> agentIds = new List<Id>{};
    List<Contact> consToUpdate = new List<Contact>{};
    
    for(Carrier_Contract__c contract: Trigger.new){
        if(contract.Has_Paid_For_A_Case__c == TRUE && contract.RecordTypeID == '012i0000000FAWI')  
            agentIds.add(contract.Agent__c); // compile list of list of Ids found in the "Agent__c" field       
    }
    // compiles and loops through list of Contacts found in Id list from above
    for(Contact c: [select ID, Has_Paid_For_A_Case__c from Contact where ID = :contractIds]){
        if(c.Has_Paid_For_A_Case__c == FALSE){
            c.Has_Paid_For_A_Case__c = TRUE;
            constoUpdate.add(c);
        }
    }
    if(!consToUpdate.isEmpty())
        update consToUpdate;
}

 

 

Since you're learning APEX, I strongly recommend reading through this best practice guide: http://wiki.developerforce.com/page/Apex_Code_Best_Practices

LloydSilverLloydSilver

Thanks much, and I appreciate the great link.

 

Confused about one part. In the code below, is :contractIds correct? I don't see that variable referenced anywhere else. Should it be instead :agentIds ?

 

 for(Contact c: [select ID, Has_Paid_For_A_Case__c from Contact where ID = :contractIds]){
k_bentsenk_bentsen

Yes, it should. I changed the list variable name to make it something more meaniful, and forgot to change its reference there..

LloydSilverLloydSilver

Cool. At least I'm figuring it out : )

 

Last question, what's the purpose of:

 

List<String> contractNames = new List<String>{};

 

I'm not seeing contractNames used anywhere.

 

Thanks.

k_bentsenk_bentsen

I'm not sure, you had it in your trigger to begin with :)

LloydSilverLloydSilver

Ah yeah. Thanks. I had started to bulkify it and then got lost but left that in there. Thanks.