function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Afzaal HassanAfzaal Hassan 

Move recordType query out of loop

I have a trigger written that basically looks at the record type and for each account in that record type, checks/validates to see if the field is entered by user or not. The trigger works, however I put a query inside the for loop, which I realized is bad practice when I started to recieve System.Exception Limit errors. Can someone please help me rewrite this. Whats throwing me off is that the trigger has a RecordType object and I have not worked with that before.

trigger CancelledBrokerValidation on Account (before update) [
    for (Account acc : Trigger.new) {
        List<RecordType> test = [SELECT Name FROM RecordType where Id =: acc.RecordTypeId];
       System.debug('RecordType size: '+test.size());
        if (!test.isEmpty()) {
           System.debug('RecordType: '+test[0].Name);
            if ((acc.Email_Templates__c == '' || acc.Email_Templates__c == null) && test[0].Name == 'Client Form Cancelled' && acc.Payee_Type__c == 'Broker') {
                System.debug('Final Step: Field is required');
                acc.Email_Templates__c.addError('Cancelled Broker Email Template Field is required.');
           } 
        }
    }
}

I tried to take a crack at rewriting this but am stuck. This is what I have done so far:

trigger CancelledBrokerValidation on Account (before update) {
    List<RecordType> accountRecords = [SELECT Id, Name FROM RecordType where Id IN :Trigger.newMap.keySet()];
    //Map<Id,RecordType> accountRecords = new Map<Id,RecordType>([Select id,Name from RecordType where Id IN: Trigger.newMap.keySet()]);
    List<Account> accountsToupdate = new List <Account>();
    Map<Id, RecordType> clientToRecordMap = new Map<Id, RecordType>();
    
    for(Account acc : accountRecords){
        System.debug('RecordType size: '+acc.size());
    }
}
Thats why I was saying I am confused with the recordType object because the for loop is not correct and recordType doesnt seem to have a size object (throwing that error)
Any help will be greatly appreciated
Thank you
Abdul KhatriAbdul Khatri
try this
 
trigger CancelledBrokerValidation on Account (before update) {

	List<Id> idRecType = new List<Id>();
    
    for(Account acct : trigger.new) {
        
        if(acct.RecordTypeId == null) continue;
        
        idRecType.add(acct.RecordTypeId);
    }
    
    if(idRecType.isEmpty()) return;

	List<RecordType> recTypeList = [SELECT Id FROM RecordType WHERE Id IN :idRecType];
    
    if(recTypeList == null) return;
    
    for (Account acc : Trigger.new) {
		if ((acc.Email_Templates__c == '' || acc.Email_Templates__c == null) && test[0].Name == 'Client Form Cancelled' && acc.Payee_Type__c == 'Broker') {
            System.debug('Final Step: Field is required');
            acc.Email_Templates__c.addError('Cancelled Broker Email Template Field is required.');
        } 
    }
}

 
Afzaal HassanAfzaal Hassan
Hi @Abdul Khatri, In your code, shouldnt test[0].Name in line 19 be recTypeList[0].Name? Also, should I add Name in the select statement for recTypeList? Test[0] is nowhere in the code so I just wanted to make sure if that is correct or not. Thank you
Prashant Pandey07Prashant Pandey07
Hi Afzaal,

+1 for Abdul..I would not recommend the uasge of recTypeList[0].Name..because may be in future you may have more record type then this code will break..also we can avoid the query in the loop..

In summer 2018 we can get more efficently record type. You can use the following methods to get the developer name.
  • Schema.DescribeSObjectResult.getRecordTypeInfosByDeveloperName()
  • Schema.RecordTypeInfo.getDeveloperName()
I will be sharing a blog on this soon.
trigger CancelledBrokerValidation on Account (before update) {
  
    Id recTypeId = Schema.getGlobalDescribe().get('Account').getDescribe().getRecordTypeInfosByName().get('Client    Form Cancelled').getRecordTypeId();

    Schema.SObjectType objType = Schema.getGlobalDescribe().get('Account');
    Schema.DescribeSobjectResult objTypeDesc = objType.getDescribe();
    map<Id, Schema.RecordTypeInfo> recTypeMap = objTypeDesc.getRecordTypeInfosById();
    Schema.RecordTypeInfo rtByName =  recTypeMap.get(recTypeId);

      for (Account acc : Trigger.new) {
      if ((acc.Email_Templates__c == '' || acc.Email_Templates__c == null) && rtByName.Name == 'Client Form Cancelled' && acc.Payee_Type__c == 'Broker') {   
            System.debug('Final Step: Field is required');
            acc.City__c.addError('Cancelled Broker Email Template Field is required.');
        } 
    
}

Let me know if this help you..

--
Thanks,
Prashant
Abdul KhatriAbdul Khatri
Hi Afzaal,

The code was the base given to you as you requested to remove the query from the loop. You can also use the following, replace the name.
Id idRecType = Schema.SObjectType.Account.getRecordTypeInfosByName().get('Development').getRecordTypeId();
I am not sure where Prashant found query in the loop in my code. My code is as per the best practise and simple for a beginner to understand.
 
Afzaal HassanAfzaal Hassan
Hello
So @Abdul Khatri code seems to be working for now (although I havent tested after the data load). When I used @Prashant code, it seemed to cause problems and stall my workflows. So Abdul are you saying that insterad of using rectypeList[0].Name in the if statment, I should replace it by the line you wrote above? I am a little confused by the code. I think Prashant has a good point, if that rectypeList has 150 records in the list, then wouldnt that cause problems still? 
Prashant Pandey07Prashant Pandey07
Hi Afzaal,

What error are you getting with my code...

--
Thanks,
Prashant
Abdul KhatriAbdul Khatri
I simplified the code and this should not have any issues what you have concerned about
 
trigger CancelledBrokerValidation on Account (before update) {

	List<Account> accountList = new List<Account>();
    
	Id idRecType = Schema.SObjectType.Account.getRecordTypeInfosByName().get('Client Form Cancelled').getRecordTypeId();
       
    for(Account acct : trigger.new) {
        
        if(acct.RecordTypeId != idRecType) continue;
        
        accountList.add(acct);
    }
    
    if(accountList.isEmpty()) return;
       
    for (Account acc : accountList) {
		if ((acc.Email_Templates__c == '' || acc.Email_Templates__c == null) && acc.Payee_Type__c == 'Broker') {
            System.debug('Final Step: Field is required');
            acc.Email_Templates__c.addError('Cancelled Broker Email Template Field is required.');
        } 
    }
}