0

I am receiving

System.LimitException: Too many SOQL queries: 101

error because of my Apex trigger.

Issue is clear but I am thinking of best possible way to handle it during bulk data loads. We will have at max of 500 tasks to load usually, so is batch apex needed or can handle it somehow only in trigger? Here Contact(WhoId) is not child object, so for each row, we need to query on Contacts and if validation fails, just add error to file and proceed with next row when dealing with Dataloader, else just add an error before save.

trigger ValidateContStatus_Task on Task (before insert, before update)
{

   for(Task t : trigger.new)
   {
   //If condition checks if it's not Lead
      if(t.whoId != NULL && String.valueOf(t.whoId).startsWith('00Q')== FALSE)
       {
           Contact c = [SELECT Id, Contact_Status__c from Contact where Id =: t.WhoId Limit 100];
           if(C.Contact_Status__c == 'Inactive')
           {
               t.whoId.addError('This Contact is Inactive, please pick an Active Contact');
           }
        }
    }
}
2
  • Have you tried going through developer.salesforce.com/page/… ? Oct 30, 2018 at 17:24
  • Yes I did. if it has DML operation, I know how to handle it. Here it's just adding error, not sure how to do it. And sorry if my question is too simple for this group. Any other link helps.!!
    – Amulya
    Oct 30, 2018 at 17:30

1 Answer 1

2

You need to bulkify your trigger. You can do this even with a polymorphic lookup like WhoId.

The pattern is basically to accumulate WhoIds in a set, perform one query to source the data, and then iterate over Trigger.new again to perform actions.

   Set<Id> contactIds = new Set<Id>();
   for (Task t : Trigger.new) {
       if (t.WhoId != null && String.valueOf(t.WhoId).startsWith('003')) {
            contactIds.add(t.WhoId);
       }
   }

   Map<Id, Contact> cs = new Map<Id, Contact([SELECT Id, Contact_Status__c from Contact where Id IN :contactIds]);

   for (Task t : Trigger.new) {
       if (t.WhoId != null && String.valueOf(t.WhoId).startsWith('003')) {
           Contact c = cs.get(t.WhoId);

           if(c.Contact_Status__c == 'Inactive') {
               t.WhoId.addError('This Contact is Inactive, please pick an Active Contact');
           }
        }
    }

This will allow you to efficiently process bulk loads, and it'll run faster too.

6
  • Thank you. Tried this, it's giving below error at line where we are validating Contact Status, though Contact exists. execution of BeforeInsert: 'System.NullPointerException: Attempt to de-reference a null object'
    – Amulya
    Oct 30, 2018 at 17:51
  • That should not happen. Would you please edit your current version into your question (as a new section, don't replace the code that's there)?
    – David Reed
    Oct 30, 2018 at 17:54
  • I have copy pasted the same code you provided. The issue here is, in between if it finds a Contact which doesn't exist, then it's marking the whole load as error. I am trying to fine tune it.
    – Amulya
    Oct 30, 2018 at 18:01
  • Is this code running in a with sharing trigger handler?
    – David Reed
    Oct 30, 2018 at 18:06
  • 1
    line 3 alternative if (t.WhoId != null && t.WhoId.getSobjectType() == Contact.SObjectType) for improved self-doc.
    – cropredy
    Oct 31, 2018 at 4:21

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.