Database Triggers

Triggers are Apex code working in concert with the Force.com database engine, automatically invoked by Force.com when database records are modified. Trigger code can perform any necessary processing on the modified data before or after Force.com completes its own work. The following list describes scenarios commonly implemented with triggers:

Image A validation rule is required that is too complex to define on the database object using formula expressions.

Image Two objects must be kept synchronized. When a record in one object is updated, a trigger updates the corresponding record in the other.

Image Records of an object must be augmented with values from another object, a complex calculation, or external data via a Web service call.

This subsection covers the essentials of trigger development, including definition, batch processing, and error handling.

Definition

A trigger definition consists of four parts:

1. A unique trigger name to differentiate it from other triggers. Multiple triggers can be defined on the same database object.

2. The name of the database object on which to create the trigger. You can create triggers on standard and custom objects.

3. A comma-separated list of one or more trigger events that cause the trigger code to be executed. An event is specified using two keywords. The first keyword is either before or after, indicating that the trigger is to be executed before or after the database operation is saved. The second keyword is the DML operation: insert, update, delete, or undelete. For example, the trigger event before update means that the trigger is fired before a record is updated. Note that before undelete is an invalid trigger event.

4. The block of Apex code to execute when the trigger event occurs. The code typically loops over the list of records in the transaction and performs some action based on their contents. For insert and update triggers, the list of records in the transaction is provided in the variable Trigger.new. In a before trigger, these records can be modified. In update, delete, and undelete triggers, Trigger.old contains a read-only list of the original versions of the records. Also available to your trigger code is a set of Boolean variables indicating the event type that fired the trigger. They are useful when your trigger is defined on multiple events yet requires separate behavior for each. These variables are Trigger.isBefore, Trigger.isAfter, Trigger.isInsert, Trigger.isUpdate, Trigger.isDelete, and Trigger.isUndelete.

Listing 4.39 is an example of a trigger named validateTimecard. It is triggered before inserts and updates to the Timecard custom object. It doesn’t do anything yet because its code block is empty.

Listing 4.39 Trigger Definition


trigger validateTimecard on Timecard__c(before insert, before update) {
  // code block
}


Triggers cannot be created in the Execute Anonymous view. Create them in the Force.com IDE by selecting File, New, Apex Trigger. To test triggers, use the native user interface to manually modify a relevant record, or write a unit test and invoke it from the Apex Test Runner or Execute Anonymous view.


Tip

A best practice for organizing trigger logic is to place it in an Apex class rather than the body of the trigger itself. This does not change anything about the behavior of the trigger or its governor limits, but encourages code reuse and makes the trigger easier to test.


Batch Processing in Triggers

Manual testing in the native user interface and simplistic unit tests can lull you into the false belief that triggers operate on a single record at a time. Not to be confused with Batch Apex, triggers can always be invoked with a list of records and should be optimized accordingly. Many ways exist to get a batch of records into the Force.com database, including the Data Loader and custom user interfaces. The surest way to a production issue with governor limits is to write a trigger that operates inefficiently when given a batch of records. The process of hardening a trigger to accept a batch of records is commonly called bulkifying the trigger.

Batches can be up to 200 records. When writing your trigger code, look at the resources consumed as you loop over Trigger.new or Trigger.old. Study the governor limits and make sure your code splits its work into batches, doing as little work as possible in the loop. For example, if you have some additional data to query, build a set of IDs from the trigger’s records and query them once. Do not execute a SOQL statement for each loop iteration. If you need to run a DML statement, don’t put that in the loop either. Create a List of objects and execute a single DML statement on the entire List. Listing 4.40 shows an example of looping over a batch of Contact records (in the variable contacts) to produce a list of Assignment records to insert.

Listing 4.40 Batching DML Operations


List<Assignment__c> toInsert = new List<Assignment__c>();
for (Contact contact : contacts) {
  toInsert.add(new Assignment__c(
    Contact__r = contact));
}
insert toInsert;


Error Handling

Errors are handled in triggers with try, catch blocks, consistent with other Apex code. But uncaught errors within a trigger differ from other Apex code in how they can impact execution of the larger database transaction the trigger participates in.

A common use of errors in triggers is for validation. Strings describing validation errors can be added to individual records or fields using the addError method. Force.com continues to process the batch, collecting any additional errors, and then rolls back the transaction and returns the errors to the initiator of the transaction.


Note

Additional error-handling behavior is available for transactions initiated outside of Force.com; for example, through the SOAP API. Records can fail individually without rolling back the entire transaction. This is discussed in Chapter 10, “Integration with Force.com.”


If an uncaught exception is encountered in a trigger, whether thrown by the system or the trigger code itself, the batch of records is immediately aborted, and all changes are rolled back.

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

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