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
Afrose AhamedAfrose Ahamed 

how to move transaction into async process when exceeding limit

Hi All,
Greetings of the day! 
Below mentioned two lines are exceeding governor limits. I want to change this below mentioned  line with condition based. If query rows is below 50000 and DML rows below 10000 then its should be in sync process if above it should be in async process. which is best batch apex or scheduled apex and how i can change the code and how can i wrote batch apex or scheduled apex. Please some one help me on this.
//some times this query exceeding more than 50000 rows and giving an error
        List<Obj2__c> obj2new = [SELECT id,name,(SELECT name FROM objs1__r) FROM Obj2__c WHERE id in : paramids];


//some times this line exceeding 10000 dml rows and giving an error
        RecordsManager.InsertAsSystem( paramnewlist );
 
trigger ParamsUpdate on Obj1__c (after insert, after update ) {
    
    if(trigger.IsAfter && (trigger.IsInsert || trigger.IsUpdate))    
    {
    List<String> obj2Ids = new List<String>();
	
    for( Obj1__c objs: Trigger.New){
        obj2Ids.add ( objs.Obj2__c);
    }
        
    
    List<Obj3__c> obj3ids = [SELECT id, Obj4__c FROM Obj3__c WHERE obj2__c IN : obj2Ids];
    
    List<String> obj4idlst= new List<String>();
    
    for( Obj3__c obj3 : obj3ids){
        obj4idlst.add( obj3.Obj4__c);
    }
    
        
        MyLogics.updateParams ( obj4idlst ); 
        }
        
}
 
public with sharing class MyLogics{
   
    public static void updateParams( List<String> obj4idlst ){
          
        Map<String,List<String>> paramsMap = new Map<String,List<String>>();
        
        List<Obj3__c> oldparams = [SELECT id FROM Obj3__c WHERE Obj4__c IN : obj4idlst ];  
        
        RecordsManager.DeleteAsSystem( oldparams );
         // Delete oldparams;  
 
        
        List<Obj4__c> Objs4 = [SELECT id,name,(SELECT id,name,Obj2__c FROM Objs3__r) FROM Obj4__c WHERE id IN : obj4idlst];
        List<String> paramids = new List<String>();
        
       
        
        for( Obj4__c obj4: Objs4){ 
            for( Obj3__c lst : obj4.Objs3__r){
                paramids.add ( lst.Obj2__c );
            } 
            	
        }
        
        //this query exceeding morethan 50000 rows
        List<Obj2__c> obj2new = [SELECT id,name,(SELECT name FROM objs1__r) FROM Obj2__c WHERE id in : paramids];
        
        
        List<String> tempParam = new List<String>();
        for( Obj2__c func: obj2new){
           
            for( Obj1__c Param : func.objs1__r ){
                tempParam.add ( Param.Name );
            }      
            paramsMap.put ( func.Id, tempparam);
        }
        
        
        
        List<Obj3__c> paramnewlist = new List<Obj3__c>();
        for( Obj4__c lsts: Objs4){ 
            for( Obj3__c FTS : lsts.objs3__r ){
                if( paramsMap.get ( FTS.Obj2__c) != null){
                    for( String parameterName : paramsMap.get ( FTS.Obj2__c )){
                        paramnewlist.add( new Obj3__c( name=parameterName, Obj4__c=lsts.Id));
                    }
                }    
            } 
        }
       //this line exceeding 10000 dml rows   
        RecordsManager.InsertAsSystem( paramnewlist );
          
    }  
}

Regards,
Afrose Ahamed M.G.
Shri RajShri Raj

You can move the parts of the code that are exceeding governor limits to a batch apex or scheduled apex class. Here's how you can modify your code:
 
global class ParamsUpdateBatch implements Database.Batchable<String> {
 
    private List<String> obj4idlst;

    public ParamsUpdateBatch(List<String> obj4idlst) {
        this.obj4idlst = obj4idlst;
    }
 
    public Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator('SELECT Id, Name, (SELECT Id, Name, Obj2__c FROM Objs3__r) FROM Obj4__c WHERE Id IN : obj4idlst');
    }
 
    public void execute(Database.BatchableContext bc, List<Obj4__c> scope) {
        Map<String, List<String>> paramsMap = new Map<String, List<String>>();
        List<String> paramids = new List<String>();

        for (Obj4__c obj4 : scope) {
            for (Obj3__c lst : obj4.Objs3__r) {
                paramids.add(lst.Obj2__c);
            }
        }

        // This query exceeding more than 50000 rows
        List<Obj2__c> obj2new = [SELECT Id, Name, (SELECT Name FROM objs1__r) FROM Obj2__c WHERE Id IN :paramids];

        List<String> tempParam = new List<String>();
        for (Obj2__c func : obj2new) {
            for (Obj1__c Param : func.objs1__r) {
                tempParam.add(Param.Name);
            }
            paramsMap.put(func.Id, tempParam);
        }

        List<Obj3__c> paramnewlist = new List<Obj3__c>();
        for (Obj4__c lsts : scope) {
            for (Obj3__c FTS : lsts.objs3__r) {
                if (paramsMap.get(FTS.Obj2__c) != null) {
                    for (String parameterName : paramsMap.get(FTS.Obj2__c)) {
                        paramnewlist.add(new Obj3__c(Name = parameterName, Obj4__c = lsts.Id));
                    }
                }
            }
        }

        // This line exceeding 10000 DML rows
        RecordsManager.InsertAsSystem(paramnewlist);
    }
 
    public void finish(Database.BatchableContext bc) {
    }
}
Here is the trigger
trigger ParamsUpdate on Obj1__c (after insert, after update ) {
    
    if(trigger.IsAfter && (trigger.IsInsert || trigger.IsUpdate))    
    {
    List<String> obj2Ids = new List<String>();
	
    for( Obj1__c objs: Trigger.New){
        obj2Ids.add ( objs.Obj2__c);
    }
        
    List<Obj3__c> obj3ids = [SELECT id, Obj4__c FROM Obj3__c WHERE obj2__c IN : obj2Ids];
    
    List<String> obj4idlst= new List<String>();
    
    for( Obj3__c obj3 : obj3ids){
        obj4idlst.add( obj3.Obj4__c);
    }
    
    if (obj4idlst.size() <= 50000 && obj2Ids.size() <= 10000) {
        MyLogics.updateParamsSync( obj4idlst ); 
    } else {
        AsyncUpdateParamsJob job = new AsyncUpdateParamsJob();
        job.obj4idlst = obj4idlst;
        job.obj2Ids = obj2Ids;
        job.run();
    }
    }
}
My logics class
public with sharing class MyLogics{
   
    public static void updateParams( List<String> obj4idlst ){
          
        Map<String,List<String>> paramsMap = new Map<String,List<String>>();
        
        List<Obj3__c> oldparams = [SELECT id FROM Obj3__c WHERE Obj4__c IN : obj4idlst ];  
        
        RecordsManager.DeleteAsSystem( oldparams );
 
        
        List<Obj4__c> Objs4 = [SELECT id,name,(SELECT id,name,Obj2__c FROM Objs3__r) FROM Obj4__c WHERE id IN : obj4idlst];
        List<String> paramids = new List<String>();
        
       
        
        for( Obj4__c obj4: Objs4){ 
            for( Obj3__c lst : obj4.Objs3__r){
                paramids.add ( lst.Obj2__c );
            } 
            	
        }
        
        //this query exceeding morethan 50000 rows
        List<Obj2__c> obj2new = [SELECT id,name,(SELECT name FROM objs1__r) FROM Obj2__c WHERE id in : paramids];
        
        
        List<String> tempParam = new List<String>();
        for( Obj2__c func: obj2new){
           
            for( Obj1__c Param : func.objs1__r ){
                tempParam.add ( Param.Name );
            }      
            paramsMap.put ( func.Id, tempparam);
        }
        
        
        
        List<Obj3__c> paramnewlist = new List<Obj3__c>();
        for( Obj4__c lsts: Objs4){ 
            for( Obj3__c FTS : lsts.objs3__r ){
                if( paramsMap.get ( FTS.Obj2__c) != null){
                    for( String parameterName : paramsMap.get ( FTS.Obj2__c )){
                        paramnewlist.add( new Obj3__c( name=parameterName, Obj4__c=lsts.Id));
                    }
                }    
            } 
        }
       //this line exceeding 10000 dml rows   
        RecordsManager.InsertAsSystem( paramnewlist );
          
    }  
}

 
Afrose AhamedAfrose Ahamed

Hi @Shri Raj,

Thanks for your response,

Great! but here i noticed in my trigger is not querying more records. In my apex class querying more records. Below is the line that is querying more records.how can i change  that based on records retrived. Like here i need to aggregate result or what? Can you please help explain and how we can query based on count.

//this query exceeding morethan 50000 rows
        List<Obj2__c> obj2new = [SELECT id,name,(SELECT name FROM objs1__r) FROM Obj2__c WHERE id in : paramids];
 
//this line exceeding 10000 dml rows   
        RecordsManager.InsertAsSystem( paramnewlist );

Regards,
Afrose Ahamed M.G.
Afrose AhamedAfrose Ahamed
Hi @Shri Raj,

If we query more than 50000 rows mean it will show error in sync process.then how the condition will check here? if its exceed the limit the same error occurs right.? Can you please help to understand more.

 
if (obj4idlst.size() <= 50000 && obj2Ids.size() <= 10000) {
 MyLogics.updateParamsSync( obj4idlst ); 
}
 
Consider
//this line already querying 50000 records 
List<Obj2__c> obj2new = [SELECT id,name,(SELECT name FROM objs1__r) FROM Obj2__c WHERE id in : paramids]; if here it goes more than 50000 records it will get error and

this condition line will not execute right?
If(obj2new.size()<=50000){
my logic
}

Regards,
Afrose Ahamed M.G.