-1

I have the below code and there is a SOQL query inside for loop. I have been instructed to avoid SOQL in the loop as these are invoked for every iteration of the loop. Since i am a beginner in Salesforce i don't know how to implement that. Here's my code where i have advised to use Soql query and condition checking before for loop using a map.

if ((isTrgBefore && (isInsert||isUpdate ))){
   for( Item eachitem :newItemList ){
     if(eachItem.WhoId!=Null){
        Schema.SObjectType sobjectType = eachItem.WhoId.getSObjectType();
        String sobjectName = sobjectType.getDescribe().getName();
        if(sobjectName.equals(UTIL_Constants.SubString)){ 
                    List<Strategy> stg=[select Type from Strategy where Id=:eachItem.WhoId];
                        for(Strategy s:stg){
                            if(s.Type=='Market Strategy' || s.Type=='Market Potency'){
                            eachItem.Strategy__c = eachItem.WhoId; 
                            }
                        }
         }
     }
     setWhatIds.add(eachItem.WhatId);
  }
}

Please help Thanks

2

1 Answer 1

3

To remove the soql from loop, you would collect all the ids that you would want to use in where clause into a set, query the records once, build a map by id and within loop lookup the record and use it.

In the modified code below, look for comment 1, 2 and 3 for important bits.

if ((isTrgBefore && (isInsert||isUpdate ))){
    
    // 1. Collect ids from source list.
    Set<Id> ids = new Set<Id>();
    
    for(Item eachitem :newItemList) {    
        if (eachItem.WhoId != null) {
            ids.add(eachItem.id);
        }
    }
    
    // 2. Query all items at once and build a map by id
    Map<Id, Strategy> strategyById = new Map<Id, Strategy>([select Id, Type from Strategy where Id in :ids and (Type ='Market Strategy' or Type ='Market Potency')]);
    
    for( Item eachitem :newItemList ){

     if(eachItem.WhoId!=Null){

        Schema.SObjectType sobjectType = eachItem.WhoId.getSObjectType();
        String sobjectName = sobjectType.getDescribe().getName();

        if(sobjectName.equals(UTIL_Constants.SubString)){ 

            // 3. Get the record you looking for and use it
            Strategy s = strategyById.get(eachItem.whoId);
            if(s != null && (s.Type=='Market Strategy' || s.Type=='Market Potency')){
                eachItem.Strategy__c = eachItem.WhoId; 
            }
         }
     }

     setWhatIds.add(eachItem.WhatId);
  }
}
4
  • Strategy s = strategyById(eachItem.whoId); strategyById-Method doesnot exist or incorrect signature. May 23 at 10:21
  • Change to Strategy s = strategyById.get(eachItem.whoId); (note the .get)
    – Rob
    May 23 at 10:31
  • The above code is not working and also i need to get the records matching criteria "Market Strategy " and "market Potency" before the for loop.can someone help? May 23 at 19:29
  • You can add that condition to original query itself so it will only fetch if type is either Market Strategy or Potency. I have updated the answer
    – metasync
    May 23 at 22:42

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.