+ Start a Discussion
AngiB.ax1285AngiB.ax1285 

Old Trigger failing New Security Scan - SOQL/SOSL statements in a loop

I have the following trigger.

 

To summarize: when a record is inserted into the object of this trigger if there is a related parent record it looks up and sets 2 fields on that record.

 

trigger SetDJELFromDepreciationSchedule on Depreciation_Journal_Entry_Line__c (Before Insert) 
{      
     for(AcctSol__Depreciation_Journal_Entry_Line__c objDJEL : Trigger.new)    
     {      
        if (objDJEL.AcctSol__Depreciation_Schedule__c != null)
        {          
           AcctSol__Depreciation_Schedule__c TheDS = 
              [select AcctSol__Accum_Depr_GL_Acct__c, AcctSol__Depr_Exp_GL_Acct__c from         
              AcctSol__Depreciation_Schedule__c where Id  
              = :ObjDJEL.AcctSol__Depreciation_Schedule__c];                        
           if(objDJEL.AcctSol__Credit_GL_Account__c == null)          
           {              
            objDJEL.AcctSol__Credit_GL_Account__c = TheDS.AcctSol__Accum_Depr_GL_Acct__c;          
           }          

           if(objDJEL.AcctSol__Debit_GL_Account__c == null)          
           {              
            objDJEL.AcctSol__Debit_GL_Account__c = TheDS.AcctSol__Depr_Exp_GL_Acct__c;          
           }     
      }    
  } 
}

 This code was written back in May and I can confirm that it works. But now all of a sudden the Force.com Security Source Code scanner is rejecting it.

 

CWE ID 10540

This rule identifies Apex where SOQL (salesforce.com Object Query Language) or SOSL (salesforce.com Object Search

Language) statements are executed within a loop.

 

I would ask how this code passed a test a couple weeks ago and now fails but I guess I don't really care - 'tis not my business to understand the rules - just to obey them :-)

 

I was wondering if someone could show me the easiest way to solve this problem ?

(I have some theories but I am also very new at this so I want to check with someone with more experience)

 

Thanks in Advance for your Assistance,

AngiB

 

Best Answer chosen by Admin (Salesforce Developers) 
Leon MorockiLeon Morocki

You can aggregate the ids and query AcctSol__Depreciation_Schedule__c object in bulk at the beginning of the trigger:

 

Set<Id> ids = new Set<Id>();
for (AcctSol__Depreciation_Journal_Entry_Line__c objDJEL : Trigger.new)
    ids.add(ObjDJEL.AcctSol__Depreciation_Schedule__c);

Map<Id, AcctSol__Depreciation_Schedule__c> schedulesMap = new Map<Id, AcctSol__Depreciation_Schedule__c>([select AcctSol__Accum_Depr_GL_Acct__c, AcctSol__Depr_Exp_GL_Acct__c from AcctSol__Depreciation_Schedule__c where Id in :ids]);

Then, in the loop, you can replace:

           AcctSol__Depreciation_Schedule__c TheDS = 
              [select AcctSol__Accum_Depr_GL_Acct__c, AcctSol__Depr_Exp_GL_Acct__c from         
              AcctSol__Depreciation_Schedule__c where Id  
              = :ObjDJEL.AcctSol__Depreciation_Schedule__c];                        

with the object taken from the pre-fetched map:

AcctSol__Depreciation_Schedule__c TheDS = schedulesMap.get(ObjDJEL.AcctSol__Depreciation_Schedule__c);