Question

I have an issue with dataloader while trying to load 8,000 records that fires the following trigger that gives me an error System.LimitException: Too many SOQL queries: 101 because of this issue ..

trigger BeforeTaskTrigger on Task (after insert, after update) {
    for(Task s : Trigger.new)
    {

        if ((s.Type == 'QRC')&&(s.Status=='Completed')) {
                BusinessLogic.processUpdateInsertTask(s);
    }
}
}


public static void processUpdateInsertTask (Task s){
         List<Task> itemList = [select Id, Type, Status, ActivityDate, OwnerId from Task where accountId = :s.AccountId and status = 'Completed' and Type ='QRC' Order By ActivityDate Desc ];
     List<Event> eventList = [select Id, Type, Status__c, ActivityDate, OwnerId, endDateTime from Event where accountId = :s.AccountId and Status__c = 'Completed' and Type ='QRC' Order By endDateTime Desc ];

        List<Account> accountData = [Select Id, Last_QRC_Date__c, Last_QRC_FA__c from Account where Id = :s.AccountId];
        if ((accountData!=null)&&(accountData.size()>0)){
            Date eventDate;
            if (eventList != null && eventList.size()>0){
         eventDate = date.newinstance(eventList.get(0).endDateTime.year(), eventList.get(0).endDateTime.month(), eventList.get(0).endDateTime.day());
        }
        if ((itemList != null)&&(itemlist.size()>0)&&(eventList!=null)&&(eventList.size()>0)){

        if (itemList.get(0).ActivityDate >= eventDate){
                accountData.get(0).Last_QRC_Date__c = itemList.get(0).ActivityDate;
                accountData.get(0).Last_QRC_FA__c = itemList.get(0).OwnerId;
                                update accountData;

        }
      else {
                accountData.get(0).Last_QRC_Date__c = eventDate;
                accountData.get(0).Last_QRC_FA__c = eventList.get(0).OwnerId;
                                update accountData;

      }
     }
     else if ((itemList != null)&&(itemlist.size()>0)){
                   processTaskSpecialCases(accountData, itemList);

     }
     else if ((eventList!=null)&&(eventList.size()>0)){
            processEventSpecialCases(accountData, eventDate, eventList);


       }
          else {
            processDeletionCases (accountData);

      }


      }
  }

I'll be glad if you can help me with rephrasing the SOQL query to be more efficient.

Was it helpful?

Solution

You need to move the queries populating itemList and eventList outside of your for loop. Traditionally, when you need information like that, you query everything you need once and then put it into a map for looking up later.

For instance:

// Get all the Account Ids
List<String> accountIds = new List<String>();
for (Task t : Trigger.new)
{
  accountIds.add(t.AccountId);
}

Map<String, List<Task>> taskMap = new Map<String, List<Task>>(); // keyed by AccountId
for (Task t : [select Id, AccountId, Type, Status, ActivityDate, OwnerId from Task where accountId = :accountIds and status = 'Completed' and Type ='QRC' Order By ActivityDate Desc ])
{
  List<Task> tasks = new List<Task>();
  if (taskMap.containsKey(t.AccountId))
  {
    tasks = taskMap.get(t.AccountId);
  }
  tasks.add(t);
  taskMap.put(t.AccountId, tasks);
}

This example based on the itemList above gets you a Map keyed by the Account ID of all the Tasks belonging to that Account. When you need to reference that list, you just key into the map and get the value (and best of all, it only counts as a single SOQL query that you can use across your entire trigger).

Take a look at the APEX Best Practices, bulkifying your code is a huge part of developing scalable Salesforce applications.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top