A trigger is a piece of code that is automatically execute in response to certain events on Salesforce records. Triggers enable you to perform custom actions before or after events to record changes, log events, send immediate notifications, and more.
For example, you might want to create a trigger that:
- Automatically assigns tasks to a user when they are created
- Sends an email notification when a task is completed
- Creates a new task when a task is completed
- Updates a custom field on the record when it’s changed
When to Use Triggers:
Triggers can be used for a variety of purposes, such as:
- Validating data entered by users
- Updating data in related records
- Logging changes to records
- Sending notifications about record changes
- Automatically assigning tasks or events when records are created or updated
Guidelines for Using Triggers:
When designing triggers, keep the following points in mind:
- Triggers should be bulk safe. That is, they should handle multiple records being insert, update, or delete in a single operation.
- Triggers should be written to handle errors gracefully. For example, if a record fails to insert or update due to a validation error, the trigger should not prevent other records from being process.
- Avoid recursion by designating one “master” trigger per object. This trigger can then call child triggers as needed.
- Avoid using SOQL or DML statements inside FOR loops. Instead, use bulk methods such as Database.query() or Database.update().
Example:
The following trigger counts the number of complete tasks for a contact and updates the Contact’s Num_Completed_Tasks custom field.
trigger UpdateNumCompletedTasks on Task (before insert, before update) {
Map<Id, Integer> contactTaskCounts = new Map<Id, Integer>();
// Loop through all the tasks being insert or update for (Task t :Trigger.new) {
// If the task is being complete, increment the count for its associate contact
if (t.Status == ‘Completed’) {
if (!contactTaskCounts.containsKey(t.ContactId)) {
contactTaskCounts.put(t.ContactId, 0);}
contactTaskCounts.put(t.ContactId, contactTaskCounts.get(t.ContactId) + 1);}}
// Get the contacts being updated so we can update their Num_Completed_Tasks field List<Contact> contactsToUpdate = new List<Contact>();
for (Id contactId : contactTaskCounts.keySet()) {
contactsToUpdate.add(new Contact(Id = contactId, Num_Completed_Tasks__c = contactTaskCounts.get(contactId)));}
// Update the contacts update contactsToUpdate;}
Update the contacts:
The trigger first creates a map to store the number of completed tasks for each contact. It then loops through all the tasks being insert or update, and increments the count for each task’s associated contact in the map.
Finally, the trigger gets a list of contacts being update and updates their Num_Completed_Tasks field with the values from the map.
Note that this trigger is bulk safe and handles errors gracefully. If a task fails to insert or update due to a validation error, the trigger will still process other tasks.
This trigger can be further optimize by using a bulk DML operation to update the Num_Completed_Tasks field for all contacts in a single operation.
trigger UpdateNumCompletedTasks on Task (before insert, before update) {
Map<Id, Integer> contactTaskCounts = new Map<Id, Integer>();
// Loop through all the tasks being insert or update for (Task t :Trigger.new) {
// If the task is being complete, increment the count for its associate contact
if (t.Status == ‘Completed’) {
if (!contactTaskCounts.containsKey(t.ContactId)) {
contactTaskCounts.put(t.ContactId, 0);}
contactTaskCounts.put(t.ContactId, contactTaskCounts.get(t.ContactId) + 1);}}
// Get the contacts being updated so we can update their Num_Completed_Tasks field List<Contact> contactsToUpdate = new List<Contact>();
for (Id contactId : contactTaskCounts.keySet()) {
contactsToUpdate.add(new Contact(Id = contactId, Num_Completed_Tasks__c = contactTaskCounts.get(contactId)));}
// Update the contacts in a single operation Database.update(contactsToUpdate);}
The trigger first creates a map to store the number of completed tasks for each contact. It then loops through all the tasks being insert or update, and increments the count for each task’s associate contact in the map.
Finally, the trigger gets a list of contacts being update and updates their Num_Completed_Tasks field with the values from the map in a single operation. This is much more efficient than updating each contact individually.
Conclusion:
In conclusion, it is important to consider the following when writing bulk triggers:
- Avoid using SOQL or DML statements inside FOR loops. Instead, use bulk methods such as Database.query() or Database.update().
- Use maps to store data from Trigger.new so that you can access it more efficiently later on.
- Use bulk DML operations to update records in a single operation. This is much more efficient than updating each record individually.
By following these guidelines, you can write bulk triggers that are efficient and easy to maintain.