Safety in numbers

Now we have a basic trigger under our belt. Let's look at what might happen if we fire that trigger with one record. If this trigger fires with a single contact record, it will update every case related to that contact whenever the contact's phone number is changed. However, triggers rarely run with only one record, and because of this, our example trigger has a number of flaws. If the trigger executes with two records, this trigger will only modify those cases where the contact ID matches the first contact record. However, the Salesforce1 platform does not guarantee that our triggers will fire with a single record. In fact, with this platform, it is quite clear that triggers will execute with at least 1 but no more than 200 records at a time. Because of this, we have to write our triggers to handle up to 200 records at a time. It may seem odd that 1 trigger would have to handle 200 records being updated at the same time, but remember that any code that inserts a list of records will fire a trigger with all of those records in it. For instance, the admin has just loaded 150 accounts via the data loader or a managed package updates a list of 199 contacts. Therefore, we have to write our triggers in such a way that we can handle 200 records at a time. However, 200 is our upper limit. If, for instance, a batch class has updated 400 records, the trigger would execute twice, once with the first 200, the second time with the second 200. This idea is called bulk safety. Writing triggers to be bulk safe involves ensuring that you handle your data and your trigger logic in a way that doesn't require extra database queries or DML statements. Let's take a look at the another example:

Trigger UpdateContactPhoneNumberOnCase on Contact (after update) {
  // Almost the same query as before, 
// but we're going to process the list first
  // Note how we're using an In clause to get cases where 
//the contactid is any of the contacts that were updated.
  List<Case> affectedCases = [SELECT id, mainContactPhone__c 
        FROM Case 
        WHERE contactId in
:trigger.newMap.keyset()];

  // This is the primary data structure we'll use to 
// access our data.
  // A map of contact id's -> to list of cases.
  Map<id, List<Case>> affectedCasesByContactId = new Map<Id, List<Case>>();
  // Now to populate our map
  for(Case c: affectedCases) {
  if(affectedCasesByContactId.keyset().containsKey(c.contactId)){
     affectedCasesByContactId.get(c.contactId).add(c);
    } else {
   affectedCasesByContactId.put(c.contactId, new List<Case>{c});
    }
  }

  // create a new list to hold our newly updated cases 
  // this way we can insert them all at once at the end.
  List<Case> updatedCases = new List<Case>();
  for(Id contactId: trigger.newMap.keyset()) {
  // Trap to make sure that the contact id we're working with actually
  // changed information we care about ie: the phone number.
    if(trigger.old.get(contactId).phone != trigger.new.get(contactId).phone) {
      for(Case thisCase: affectedCasesByContactId.get(contactId)) {
      // Update all the cases to with the new phone number
      thisCase.mainContactPhone__c = trigger.new.get(contactId).phone;
      // add them to our list that we'll update.
      updatedCases.add(thisCase);
      }
    }
  }

  // Always wrap your DML in try/catch blocks.
  try {
    update updatedCases;  
  } catch(Exception e) {
    System.debug(e.getMessage());
  }

}

This version of the trigger is much better. It is capable of handling multiple incoming contact records, and we've moved our DML to update the affected cases to the very end and updating them all at once as a list of records. Together, these modifications make our trigger bulk safe.

Note how we're using Map as a data structure for linking contact ids and their associated cases. There are three key takeaways here. First, we pull all the data needed from the database at the beginning of the trigger. Next, use lists of records for all DML calls. Lastly, keep all DML outside of loops. It's normal to loop over the individual items in a list to accomplish any logic or record manipulation but we need to ensure that our DML calls remain outside such loops. In fact, when writing triggers, keep all SOQL and DML outside all loops.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.114.85