Is there any way to use only one SOQL for both before and after trigger on the same object?
Yes static variables are meant for same purpose .
Create a static list in your helper class and use same in your before trigger and after trigger
public class cachequery {
public static List<Account> lstaccount= [Select Id,Name from Account LIMIT 10];
}
The sample trigger to provide an idea
trigger T1 on Account (before insert, after insert) {
list<Account> lstcached = cachequery.lstaccount;
if(Trigger.isBefore && Trigger.isInsert){
system.debug(lstcached );
}
if(Trigger.isAfter && Trigger.isInsert){
system.debug(lstcached );
}
}
This is a good time to learn about the Lazy Load
pattern. You can write your cache in such a way that you only consume the query if you actually need the data. Now if you make a reference to this Apex Class
to perform some logic that has no need for the query, you will not touch your governor limits.
public with sharing class MyService
{
public static List<Group> cachedQueues
{
get
{
if (cachedQueues == null)
{
cachedQueues = [/*query*/];
}
return cachedQueues;
}
private set;
}
}
You can do that by storing the results into a static
variable outside the trigger - perhaps in your trigger handler class.
For an example we have a trigger on Account and we want to store a list of Contacts for our before and after execution (instead of querying twice):
Trigger Handler:
public with sharing class TriggerHandler
{
public static List <Contact> contacts;
}
Then in your trigger you can set the list of contacts in the before
execution, which then will be also available in the after
execution. Both run in the same transaction and the static
variables are available throughout the whole transaction - it's the same context.
trigger AccountTest on Account (before insert, after insert)
{
if (trigger.isBefore)
{
TriggerHandler.contacts = [SELECT Id FROM Contact];
}
else
{
system.debug(TriggerHandler.contacts.size());
}
}