Trigger and Trigger Context Variables

Hello Devs, hope you all doing well.

In this post I'm gonna talk about trigger context variables in details, their consideration and which context variables is available in which trigger event i.e before/after DML.

First let's talks about some basics.

Trigger is a piece of Apex Code that execute before or after DML operations.

There are two types of trigger:-

  Before Triggers are used to assign/validate record field values before they are saving to database.

  After Triggers are used to update other records by accessing current record's field (record that is in      transaction) which are set by system (mostly we use Id and date fields).

Triggers can cause other records to change, and these changes also can, in result, it fires more triggers so apex runtime engine consider all these operation a single piece of task and sets limits on number of operations that can performed to prevent infinite recursion.


Now let's talk about trigger Implementation Considerations:-


  • Upsert trigger fires both before/after insert and before/after update event.
  • Field History Cannot be traced/recorded in trigger execution. Field History honors current user's permission i.e  if current user does not have permission to edit an object and a trigger can causes change to  that object, so in that case history cannot be traced.
  • Undelete trigger only works for specific object like Account, Asset, Contact, Opp, Campaign, Custom Objects, Event, Lead, ContentDocument, Case, Contract, Task and Solution.
  • The after undelete trigger events only run for top-level objects. (If there is any after undelete trigger on both Account and Contact, then only account undelete trigger fires).
    Ex:- If an account record is deleted, related contact may also be deleted. Undeleting (recover from recycle bin) that account also recover related contacts.
  • Callouts must be made asynchronously from triggers, so your trigger's process could not be blocked because there might be some waiting for getting response from external services.
    To make asynchronous callouts in trigger use asynchronous apex(Future method).

Context Variable Consideration :-

It's easy to confuse about accessibility of context variables in triggers events. If one has good understanding of what context variable is returning, then it become very easy and handy to use context variable in correct trigger event.

So let's discuss very first and mostly used context variable and that is "Trigger.new".
Trigger.new returns a list of records which you are just creating. So in that case you can only modified and validate field values by accessing new records in before trigger.
So it's become easy to know that one can access Trigger.new context variable in before trigger event.
In before insert event you cannot perform update and delete operation on same object record because 
record has not been created.

Similarly, "Trigger.old" returns a list of old version records which you are just updating. You cannot use Trigger.old in insert operation because there is no old version of the record you  are just creating. Accessing Trigger.old in insert event throws NullPointerException.
It returns records only in Read-Mode, so you can use current record Id to process other related sObject records.
Scenario:- Create a contact record with same old name as account on an account update.

trigger createContact on Account (before update){
    List contactList = new List();
    if(trigger.isBefore && trigger.isUpdate){
         for(Account ac : trigger.old){
            Contact ct = new Contact();
            ct.LastName = ac.Name;
            ct.AccountId = ac.Id;
            contList.add(ct);
        }
        insert contList;
    }
}

Let's discuss one more scenario, Associate child contact records of an account to another account record before deleting that account.
Explanation:- Before deleting an account you need to have deleted accountId to access related contact records and assign those child records to new account.

List contactList = new List();
if(trigger.isBefore && trigger.isDelete){
    set acIds = new set();
    for(Account ac : trigger.old){
        acIds.add(ac.Id);
   }
   for(Contact ct : [select id,accountId from Contact where AccountId IN :acIds]     {
        //give accountid to with you want to associate these child records.
        // don't give directly query it or store it in (Label,setting).
        ct.AccountId = '0000XXXXXXXXXXX';
        contactList.add(ct);
    }
    update contactList;
}

Always write Bulk trigger. BTW triggers are always bulk by default, Our block of code should be
enough flexible to process records in bulk not like one record at a time.

You can bulkify your code by following best practise like performing SOQL outside for loops, performing DML operation on a collection of records as described below.


  • Minimize the number of DML operations by adding records to collection and perform DML against the collection itself.
  • Minimize the number of SOQL query by preprocessing the records in Set and that can be used in single SOQL statement by using IN clause.

Final Bottom line is:-

Trigger.new and Trigger.newMap are not available in delete event (both before and after). Only available in insert and update event (both before and after).

Trigger.old and Trigger.oldMap are not available in insert event (beith before and after). Only available in update and delete event (both before and after).


Good Coding 😊😊

Comments

Popular posts from this blog

How to show or hide a particular section of Visualforce Page dependent upon picklistfield value

Process Automation Specialist Superbadge

Dynamically Add/Delete rows in Visualforce Page