You need to sign in to do that
Don't have an account?
AviKesari
Too many SOQL queries : 101, test class fails
Hi All,
I have trigger on after insert and after update, below is my handler class.
If i create a task from contact(is a required field on page layout) it fails because whatID is null. So I'm trying to query to get the whatID based on whoID.
If i create a task from account, works fine because whoid and whatid are not null.
public with sharing class TaskTriggerHandler {
private boolean trigger_isExecuting = false;
public TaskTriggerHandler(){
}
public void OnAfterInsert(Task[] newObjects){
// EXECUTE AFTER INSERT LOGIC updateAccountActivityFields(newObjects);
}
public void OnAfterUpdate(Task[] oldObjects, Task[] updatedObjects, Map<ID, Task> ObjectMap){
//EXECUTE AFTER UPDATE LOGIC
updateAccountActivityFields(updatedObjects);
}
public void updateAccountActivityFields(Task[] taskRecords){
// find task record type
RecordType taskRec = [SELECT Id FROM RecordType WHERE SobjectType ='Task' AND DeveloperName ='Task_Record_Type'];
List<Account> accountsToUpdate = new List<Account>();
Account a;
//Get all the contactIds and accountIds of the task being inserted/updated
for(Task tk : [SELECT Id, LastModifiedBy.name, type, LastModifiedDate, CreatedDate, RecordTypeId, whoid, whatid FROM task WHERE id in :taskRecords]){
if(tk.RecordTypeId == taskRec.Id && tk.Whoid!=null){
// query to get account ID from contact:whoID
a = new Account(Id = [SELECT AccountId FROM Contact WHERE Id =: tk.WhoId Limit 1].AccountId);
//convert task's CreatedDate, datetime to date
Date createdDateJustDate = date.newinstance(tk.CreatedDate.year(), tk.CreatedDate.month(), tk.CreatedDate.day());
//update the activity fields on account with Task's lastModifiedDate and LastModifiedBy based on Task Type
if(tk.type=='Face 2 Face Meeting' || tk.type=='Lunch'){
a.Last_Face_to_Face_Activity__c = createdDateJustDate;
a.Last_Visited_By__c = tk.LastModifiedBy.name;
}
else{
a.Last_Call_Activity__c = createdDateJustDate;
}
accountsToUpdate.add(a);
}
}
if(!accountsToUpdate.isEmpty())
Update accountsToUpdate;
My test Class :
Please help!!
public void OnAfterUpdate(Task[] oldObjects, Task[] updatedObjects, Map<ID, Task> ObjectMap){
//EXECUTE AFTER UPDATE LOGIC
System.debug('SAFELITE_DEBUG:TaskTriggerHandler:OnAfterUpdate:: updatedObjects=' + updatedObjects);
updateAccountActivityFields(updatedObjects);
}
public void updateAccountActivityFields(Task[] taskRecords){
/* when a task of RecordType(Safelite_Task_Record_Type) is created/updated either from Account or Contact then
update Account fields : Last_Face_to_Face_Activity__c, Last_Visited_By__c & Last_Call_Activity__c based on task type
*/
System.debug('SAFELITE_DEBUG:TaskTriggerHandler:updateAccountActivityFields:: taskRecords=' + taskRecords);
// find task record type
RecordType taskRec = [SELECT Id FROM RecordType WHERE SobjectType ='Task' AND DeveloperName ='Safelite_Task_Record_Type'];
System.debug('SAFELITE_DEBUG:TaskTriggerHandler:updateAccountActivityFields:: taskRec.Id=' + taskRec.Id);
List<Account> accountsToUpdate = new List<Account>();
Account a;
//Map of Account IDs and Accounts
Map<id,account> accMap = new Map<id,account>();
//Get all the contactIds and accountIds of the task being inserted/updated
for(Task tk : [SELECT Id, LastModifiedBy.name, type, LastModifiedDate, CreatedDate, RecordTypeId, whoid, whatid FROM task WHERE id in :taskRecords]){
if(tk.RecordTypeId == taskRec.Id && tk.Whoid!=null){
a = new Account(Id = [SELECT AccountId FROM Contact WHERE Id =: tk.WhoId LIMIT 100].AccountId);
System.debug('SAFELITE_DEBUG:TaskTriggerHandler:updateAccountActivityFields:: tk.WhatId=' + tk.WhatId);
//convert task's CreatedDate, datetime to date
Date createdDateJustDate = date.newinstance(tk.CreatedDate.year(), tk.CreatedDate.month(), tk.CreatedDate.day());
System.debug('SAFELITE_DEBUG:TaskTriggerHandler:updateAccountActivityFields:: createdDateJustDate=' + createdDateJustDate);
//update the activity fields on account with Task's lastModifiedDate and LastModifiedBy based on Task Type
if(tk.type=='Face 2 Face Meeting' || tk.type=='Lunch'){
a.Last_Face_to_Face_Activity__c = createdDateJustDate;
a.Last_Visited_By__c = tk.LastModifiedBy.name;
accountsToUpdate.add(a);
System.debug('SAFELITE_DEBUG:TaskTriggerHandler:updateAccountActivityFields:: Last_Face_to_Face_Activity__c=' + a.Last_Face_to_Face_Activity__c);
System.debug('SAFELITE_DEBUG:TaskTriggerHandler:updateAccountActivityFields:: Last_Visited_By__c=' + a.Last_Visited_By__c);
}
else{
a.Last_Call_Activity__c = createdDateJustDate;
accountsToUpdate.add(a);
System.debug('SAFELITE_DEBUG:TaskTriggerHandler:updateAccountActivityFields:: Last_Call_Activity__c=' + a.Last_Call_Activity__c);
}
//Populate accMap with the Account IDs and Account record
accMap.put(a.id,a);
}
}
if(!accMap.isEmpty()){
Update accMap.values();
}
}
}
My Test Class:
static testMethod void testAdminUserwithTask() {
// Next make sure that a System Admin *can* delete an attachment
Profile adminProf = [select id from profile where name='System Administrator'];
User au = new User(alias = 'Admint', email='AdminUser@asdahsdjkhkjashdjasd.com',emailencodingkey='UTF-8',FirstName='Admin',
lastname='task',languagelocalekey='en_US',localesidkey='en_US',profileid = adminProf.Id,
timezonesidkey='America/Los_Angeles',username='AdminUser@asdahsdjkhkjashdjasd.com');
// Switch current user to System Admin user
System.runAs(au) {
// Create test data (a new Account with an Attachment)
Account a = new Account(Name='Testtasking');
insert a;
Contact con = new Contact(LastName='Test',FirstName='asdasd',Email='asdasd@adsasd.com') ;
insert con ;
List<Task> tasks = new List<Task>{};
for(Integer i = 0; i < 200; i++)
{
Task t = new Task(Subject='Donni'+i,Status='New',Priority='Normal',Type='Phone Call', whoId =con.Id, whatId = a.Id );
tasks.add(t);
}
test.startTest();
insert tasks;
test.stopTest();
try {
delete tasks;
} catch (Exception e) {
}
}
}
I have trigger on after insert and after update, below is my handler class.
If i create a task from contact(is a required field on page layout) it fails because whatID is null. So I'm trying to query to get the whatID based on whoID.
If i create a task from account, works fine because whoid and whatid are not null.
public with sharing class TaskTriggerHandler {
private boolean trigger_isExecuting = false;
public TaskTriggerHandler(){
}
public void OnAfterInsert(Task[] newObjects){
// EXECUTE AFTER INSERT LOGIC updateAccountActivityFields(newObjects);
}
public void OnAfterUpdate(Task[] oldObjects, Task[] updatedObjects, Map<ID, Task> ObjectMap){
//EXECUTE AFTER UPDATE LOGIC
updateAccountActivityFields(updatedObjects);
}
public void updateAccountActivityFields(Task[] taskRecords){
// find task record type
RecordType taskRec = [SELECT Id FROM RecordType WHERE SobjectType ='Task' AND DeveloperName ='Task_Record_Type'];
List<Account> accountsToUpdate = new List<Account>();
Account a;
//Get all the contactIds and accountIds of the task being inserted/updated
for(Task tk : [SELECT Id, LastModifiedBy.name, type, LastModifiedDate, CreatedDate, RecordTypeId, whoid, whatid FROM task WHERE id in :taskRecords]){
if(tk.RecordTypeId == taskRec.Id && tk.Whoid!=null){
// query to get account ID from contact:whoID
a = new Account(Id = [SELECT AccountId FROM Contact WHERE Id =: tk.WhoId Limit 1].AccountId);
//convert task's CreatedDate, datetime to date
Date createdDateJustDate = date.newinstance(tk.CreatedDate.year(), tk.CreatedDate.month(), tk.CreatedDate.day());
//update the activity fields on account with Task's lastModifiedDate and LastModifiedBy based on Task Type
if(tk.type=='Face 2 Face Meeting' || tk.type=='Lunch'){
a.Last_Face_to_Face_Activity__c = createdDateJustDate;
a.Last_Visited_By__c = tk.LastModifiedBy.name;
}
else{
a.Last_Call_Activity__c = createdDateJustDate;
}
accountsToUpdate.add(a);
}
}
if(!accountsToUpdate.isEmpty())
Update accountsToUpdate;
My test Class :
Please help!!
public void OnAfterUpdate(Task[] oldObjects, Task[] updatedObjects, Map<ID, Task> ObjectMap){
//EXECUTE AFTER UPDATE LOGIC
System.debug('SAFELITE_DEBUG:TaskTriggerHandler:OnAfterUpdate:: updatedObjects=' + updatedObjects);
updateAccountActivityFields(updatedObjects);
}
public void updateAccountActivityFields(Task[] taskRecords){
/* when a task of RecordType(Safelite_Task_Record_Type) is created/updated either from Account or Contact then
update Account fields : Last_Face_to_Face_Activity__c, Last_Visited_By__c & Last_Call_Activity__c based on task type
*/
System.debug('SAFELITE_DEBUG:TaskTriggerHandler:updateAccountActivityFields:: taskRecords=' + taskRecords);
// find task record type
RecordType taskRec = [SELECT Id FROM RecordType WHERE SobjectType ='Task' AND DeveloperName ='Safelite_Task_Record_Type'];
System.debug('SAFELITE_DEBUG:TaskTriggerHandler:updateAccountActivityFields:: taskRec.Id=' + taskRec.Id);
List<Account> accountsToUpdate = new List<Account>();
Account a;
//Map of Account IDs and Accounts
Map<id,account> accMap = new Map<id,account>();
//Get all the contactIds and accountIds of the task being inserted/updated
for(Task tk : [SELECT Id, LastModifiedBy.name, type, LastModifiedDate, CreatedDate, RecordTypeId, whoid, whatid FROM task WHERE id in :taskRecords]){
if(tk.RecordTypeId == taskRec.Id && tk.Whoid!=null){
a = new Account(Id = [SELECT AccountId FROM Contact WHERE Id =: tk.WhoId LIMIT 100].AccountId);
System.debug('SAFELITE_DEBUG:TaskTriggerHandler:updateAccountActivityFields:: tk.WhatId=' + tk.WhatId);
//convert task's CreatedDate, datetime to date
Date createdDateJustDate = date.newinstance(tk.CreatedDate.year(), tk.CreatedDate.month(), tk.CreatedDate.day());
System.debug('SAFELITE_DEBUG:TaskTriggerHandler:updateAccountActivityFields:: createdDateJustDate=' + createdDateJustDate);
//update the activity fields on account with Task's lastModifiedDate and LastModifiedBy based on Task Type
if(tk.type=='Face 2 Face Meeting' || tk.type=='Lunch'){
a.Last_Face_to_Face_Activity__c = createdDateJustDate;
a.Last_Visited_By__c = tk.LastModifiedBy.name;
accountsToUpdate.add(a);
System.debug('SAFELITE_DEBUG:TaskTriggerHandler:updateAccountActivityFields:: Last_Face_to_Face_Activity__c=' + a.Last_Face_to_Face_Activity__c);
System.debug('SAFELITE_DEBUG:TaskTriggerHandler:updateAccountActivityFields:: Last_Visited_By__c=' + a.Last_Visited_By__c);
}
else{
a.Last_Call_Activity__c = createdDateJustDate;
accountsToUpdate.add(a);
System.debug('SAFELITE_DEBUG:TaskTriggerHandler:updateAccountActivityFields:: Last_Call_Activity__c=' + a.Last_Call_Activity__c);
}
//Populate accMap with the Account IDs and Account record
accMap.put(a.id,a);
}
}
if(!accMap.isEmpty()){
Update accMap.values();
}
}
}
My Test Class:
static testMethod void testAdminUserwithTask() {
// Next make sure that a System Admin *can* delete an attachment
Profile adminProf = [select id from profile where name='System Administrator'];
User au = new User(alias = 'Admint', email='AdminUser@asdahsdjkhkjashdjasd.com',emailencodingkey='UTF-8',FirstName='Admin',
lastname='task',languagelocalekey='en_US',localesidkey='en_US',profileid = adminProf.Id,
timezonesidkey='America/Los_Angeles',username='AdminUser@asdahsdjkhkjashdjasd.com');
// Switch current user to System Admin user
System.runAs(au) {
// Create test data (a new Account with an Attachment)
Account a = new Account(Name='Testtasking');
insert a;
Contact con = new Contact(LastName='Test',FirstName='asdasd',Email='asdasd@adsasd.com') ;
insert con ;
List<Task> tasks = new List<Task>{};
for(Integer i = 0; i < 200; i++)
{
Task t = new Task(Subject='Donni'+i,Status='New',Priority='Normal',Type='Phone Call', whoId =con.Id, whatId = a.Id );
tasks.add(t);
}
test.startTest();
insert tasks;
test.stopTest();
try {
delete tasks;
} catch (Exception e) {
}
}
}
Greetings to you!
Rewrite code that executes queries inside for loops by moving the query outside of the loop and extending it to query all necessary data.
This error appears when you exceed the Execution Governors Limit (you can run up to a total 100 SOQL queries in a single call or context): https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_gov_limits.htm
To fix the issue, change your code so that the number of SOQL fired is less than 100.
If you need to change the context, you can use @future annotation which will run the code asynchronously.
Best practices to avoid exceeding the Governors Limit:
Since Apex runs on a multi-tenant platform, the Apex runtime engine strictly enforces limits to ensure code doesn't monopolize shared resources.
Reference: https://help.salesforce.com/articleView?id=000181404&type=1
I hope it helps you.
Kindly let me know if it helps you and close your query by marking it as solved so that it can help others in the future. It will help to keep this community clean.
Thanks and Regards,
Khan Anas
You have to reduce the number of SOQL queries fron the single thread because it is hitting the limit. You can do that by reducing it in may ways. Below is one example. For getting the record type, don't use query insted you can use below code:
Old Query :
RecordType taskRec = [SELECT Id FROM RecordType WHERE SobjectType ='Task' AND DeveloperName ='Safelite_Task_Record_Type'];
No query required:
Id devRecordTypeId = Schema.SObjectType.Account.getRecordTypeInfosByName().get('Development').getRecordTypeId();
Here, 'Development' is the record type's name.
https://developer.salesforce.com/forums/?id=906F0000000937iIAA