SalesforceBlue

Feel the rhythm of Salesforce

Apex

Apex Triggers Simplified

Trigger! One must have heard this word that an event/operation triggered someone and later they did this.

This is what Apex Triggers does technically.

There is a set of predefined operations which we called as DML operations. When this DML operation is executed it triggers a set of code which we called Trigger.

Consider you logged into Salesforce and have created an Account record. This will execute the insert DML operation. If you update an account record it will execute the Update DML operation and likewise for Delete.

One can create, update or delete a record programmatically as well instead of interacting from UI. DML operations will still follow the same rule.

So what happens when a DML operation is executed and how to write logic around it.

Suppose you have a requirement to prevent the creation of duplicate contact records. Criteria to identify the duplicate records would be based upon email address or any combination of fields value on the contact record. Here we will be considering the email.

Before proceeding below please get yourself familiar with Trigger context, Apex Collections & Apex SOQL. Please go through it and come back here once done ๐Ÿ™‚


Your trigger will look like the below :

trigger ContactTrigger on Contact (before insert, before update, after undelete) {

    Set<String> emailSetNew = new Set<String>();
    Set<String> emailSetExisting = new Set<String>();

    for(Contact con : Trigger.new) {
        if(! String.isEmpty(con.Email)) {
            emailSetNew.add(con.Email); 
        }
    }

    for(Contact con : [SELECT Id, Email FROM Contact WHERE Email =: emailSetNew]) {
        emailSetExisting.add((con.Email).toUpperCase());
    }
    
    for(Contact con : Trigger.new) {
        if(! emailSetExisting.isEmpty() && emailSetExisting.contains((con.Email).toUpperCase())) {
            con.addError('Duplicate Email Found!');
        }
    }
}

Let’s understand the code :

trigger ContactTrigger on Contact (before insert, before update, after undelete) {

The above block confirms that this ContactTrigger will execute during insert, update and undelete operation. The reason to include undelete is to ensure that if deleted contact records are restored back then also there should be a duplicate check and our code should handle that.

for(Contact con : [SELECT Id, Email FROM Contact WHERE Email =: emailSetNew]) {
    emailSetExisting.add((con.Email).toUpperCase());
}

The above block creates a set of existing emails by iterating over the SOQL results. As you can see we have used toUppercase() while adding email to the set and will be using upperCase() in the below block too.

Since Set is a case-sensitive Data Structure even though Apex Language itself is case insensitive. Thus, to ensure that there is a common case in both the generated set we are using it.

for(Contact con : Trigger.new) {
    if(emailSetExisting.contains((con.Email).toUpperCase())) {
        con.addError('Duplicate Email Found!');
    }
}

In the above block, we are iterating again inside Trigger.new and emailSetExisting is checked to verify if there are existing emails already present.

Please note that Triggers execute on batches of 200 records at a time. So if 400 records cause a trigger to fire, the trigger fires twice, once for every 200 records. For this reason, you donโ€™t get the benefit of SOQL for loop record batching in triggers, because triggers batch up records as well.

There is a more cleaner and efficient approach to writing the above Trigger using Handlers. You can read more on it over here – Trigger Handler Approach.

Now you know how to write Triggers and how to even write them using Trigger Handlers, you should be aware of a potential pitfall that is ‘Trigger recursion’. Feel free to take a quick peek over here – Apex Trigger Recursion

Thank you for visiting SalesforceBlue.com
If you have any queries feel free to write down a comment below ๐Ÿ™‚


One thought on “Apex Triggers Simplified

  • Gal Jerman

    Top ,.. top top … post! Keep the good work on !

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *