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
Conor Bradley 5Conor Bradley 5 

bulkify apex trigger

Hi

I am having trouble with my apex trigger. I have written SOQL inside FOR loop which causes Exception : "System.LimitException: Too many SOQL queries: 101". Can someone help me 'bulkify' this trigger as I can't seem to do so. Many Thanks, Triger below: 
 
trigger MnCopyPrimaryContact on Opportunity (before update) {
   for (Opportunity o : Trigger.new) {
       OpportunityContactRole[] contactRoleArray =
       [select ContactID, isPrimary from OpportunityContactRole where OpportunityId = :o.id ORDER BY isPrimary DESC, createdDate];
       if (contactRoleArray.size() > 0) {
           o.Opportunity_contact__c = contactRoleArray[0].ContactID;           
       }else{
           o.Opportunity_contact__c = null;
       }
   }
 }

 
Best Answer chosen by Conor Bradley 5
Ajay K DubediAjay K Dubedi
Hi Conor,

First of all you can not use query inside for loop.
You were using SOQL and DML inside for loop which is not a best practice 
it will hit the governor limit while working with Large no of records
  
  trigger MnCopyPrimaryContact on Opportunity (before update) {
    Set<Id> setOfIds = new Set<Id>();
    for (Opportunity o : Trigger.new) {
        if(o.Id!=Null){
            setOfIds.add(o.Id);
        }
    }
    OpportunityContactRole[] contactRoleArray= [select ContactID, isPrimary from OpportunityContactRole where OpportunityId IN :setOfIds  order by isPrimary desc,CreatedDate];
    for (Opportunity o : Trigger.new) {
        if (contactRoleArray.size() > 0) {
            o.Opportunity_contact__c = contactRoleArray[0].ContactID;           
        }else{
            o.Opportunity_contact__c = null;
        }
    }
    
}
  
Please let me know if you have any query.
Please mark it as best Answer if you find it helpful.

Thank You
Ajay Dubedi

 

All Answers

Niraj Kr SinghNiraj Kr Singh
Hi Conor Bradley,

You can try this :
trigger MnCopyPrimaryContact on Opportunity (before update) { 
	if(trigger.isBefore && trigger.isUpdate) {
        Map<Id, OpportunityContactRole> oppIdVsContactRolesMap = new Map<Id, OpportunityContactRole>();
        
        for(OpportunityContactRole objRole : [SELECT ContactID, OpportunityId, isPrimary FROM OpportunityContactRole WHERE OpportunityId In:trigger.newMap.keySet() ORDER BY isPrimary DESC, createdDate]) {
            system.debug('objRole:::::  ' + objRole );
            if(!oppIdVsContactRolesMap.containsKey(objRole.OpportunityId)) {
                oppIdVsContactRolesMap.put(objRole.OpportunityId, objRole);
            }
        }
        system.debug('--Map--'+ oppIdVsContactRolesMap);
        if(!oppIdVsContactRolesMap.isEmpty()) {
            for(Opportunity objOppty : trigger.new) {
                if(oppIdVsContactRolesMap.containsKey(objOppty.Id)) {
                    system.debug('oppIdVsContactRolesMap.get(objOppty.Id).ContactID:::::  ' +oppIdVsContactRolesMap.get(objOppty.Id).ContactID );
                    objOppty.Opportunity_contact__c = oppIdVsContactRolesMap.get(objOppty.Id).ContactID;
                }
            }
        }
    }
}
Let me know if it works for you.
If works, Mark your ans.

Thanks
Niraj
 
Conor Bradley 5Conor Bradley 5
Hi Niraj

The desired outcome of this trigger is to take the contact in the 'opportunity contact role' and put it to a look up field on opportunity called opportunity_contact__c. Ordered by if its primary or then created date.

Your solution has bulkified my trigger, but it does not work for what I need it to do.

Thanks
Conor
Niraj Kr SinghNiraj Kr Singh
Hi Conor Bradley,

Means you want to link Latest created Primary OpportunityContactRole to opportunity_contact__c field, then Update the SOQL query of above code by this SOQL, (If i understood your requirements clearly):

[SELECT ContactID, OpportunityId, isPrimary FROM OpportunityContactRole WHERE OpportunityId In:trigger.newMap.keySet() AND isPrimary = true ORDER BY isPrimary DESC, createdDate]

Or
according to ur requirement you can update this SOQL statement and try. Hope it will work

Thanks
Niraj

 
Ajay K DubediAjay K Dubedi
Hi Conor,

First of all you can not use query inside for loop.
You were using SOQL and DML inside for loop which is not a best practice 
it will hit the governor limit while working with Large no of records
  
  trigger MnCopyPrimaryContact on Opportunity (before update) {
    Set<Id> setOfIds = new Set<Id>();
    for (Opportunity o : Trigger.new) {
        if(o.Id!=Null){
            setOfIds.add(o.Id);
        }
    }
    OpportunityContactRole[] contactRoleArray= [select ContactID, isPrimary from OpportunityContactRole where OpportunityId IN :setOfIds  order by isPrimary desc,CreatedDate];
    for (Opportunity o : Trigger.new) {
        if (contactRoleArray.size() > 0) {
            o.Opportunity_contact__c = contactRoleArray[0].ContactID;           
        }else{
            o.Opportunity_contact__c = null;
        }
    }
    
}
  
Please let me know if you have any query.
Please mark it as best Answer if you find it helpful.

Thank You
Ajay Dubedi

 
This was selected as the best answer
Conor Bradley 5Conor Bradley 5
Thanks Niraj and Ajay, both great answers very helpful.