3

In after triggers, if I need to further update the context records, I usually use a SOQL query to grab the records from the database, something like:

List<CPQ_Data_Import__c> relatedCdiRecords = [Select    Id, Json_PayLoad__c,
                                                                Completed__c,
                                                                External_Id_Field__c,
                                                                SObject_Type__c,
                                                                Response_Text__c,
                                                                Success__c
                                                      From CPQ_Data_Import__c 
                                                      Where Id in :Trigger.New];

Now this new list is not read-only.

However, my client prefer to utilise Trigger.New more in this case, I am fine to write the code in this manner, something like:

    for(CPQ_Data_Import__c cdi: (List<CPQ_Data_Import__c>)Trigger.New) 
    {
        CPQ_Data_Import__c cdiNew = cdi.clone();
        cdiNew.Id = cdi.Id;
        relatedCdiRecords.add(cdiNew);
    }

Both of the above approaches will work. However, the second approach is still a bit strange to me. They made a fair point that if we add more and more fields into the SObject then we don't need to alter the SOQL query again and again (which I would argue because if we need to alter the SOQL query, we will need to adjust trigger code anyway). However, I don't see an obvious issue with the second approach aside from execution efficiency - which is of the least concern.

Any suggestions on which one is a better approach?

6

You should avoid using SOQLs arbitrarily. They are a very limited resource and the first governor limit you're most likely to hit in any large system. The second version is better of the two choices. However, an even better choice is option 3: copy only the values you need to copy. That looks like this:

for(CPQ_Data_Import__c cdi: (List<CPQ_Data_Import__c>)Trigger.New) 
{
    relatedCdiRecords.add(new CPQ_Data_Import__c(id=cdi.Id,...));
}

This pattern preserves the most heap space, CPU time, and SOQL limits.

While you're right that either pattern does work, and execution efficiency only matters up to a point, I would argue that developers should learn to get in the habit of writing efficient code.

I've seen projects that were pushing right up against the limit (say 98 of 100 SOQL) that I was able to optimize down to 46 SOQL, for example. Compromising optimization in little ways like this can add up to severely compromised performance in the end.

While most of the CPU-saving optimizations are typically not necessary--the main exception to that is using Map over nested for-loops--SOQL, DML, and SOSL optimizations are almost always necessary for future stability. You shouldn't be tempted to use a SOQL query just to construct a list of records you already have ID values for and all the data for. Use SOQL strictly for obtaining row locks, if necessary, and retrieving data you don't already have access to.

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.