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
Zach DelacroixZach Delacroix 

System.LimitException: Too many DML rows: 10001 when updating records

Hi Experts,

I have created a trigger that updates three objects in one. (I know that will cause me Error just don't know how to fix it)

I heard about Batch Apex, but I have no Idea how to use this. Below is my code. I hope someone can help :)
 
public class ClsClientSignOff {

public void UpdateJobAllocation(List<Job_Allocation_Sign_Off__c> JASOs){
        
        set<id> jobid = new set<id>();
        set<id> resourceId = new set<id>();
        
        map<id,Job_Allocation_Sign_Off__c> jasomap = new map<id,Job_Allocation_Sign_Off__c>();
        
        for(Job_Allocation_Sign_Off__c jaso : [select id, name, Client_Sign_Off__r.job__c, Resource__c,StartTravel__c, FinishTravel__c,StartJob__c,FinishJob__c,Resource_Type__c,StartOdometer__c, Start_Break__c, End_Break__c
                                               from Job_Allocation_Sign_Off__c 
                                               where id in:JASOs]){
                                                   
            jobid.add(jaso.Client_Sign_Off__r.job__c);
            resourceId.add(jaso.Resource__c);
            jasomap.put(jaso.Id, jaso);
                                                   
        }
        
        list<sked__Job_Allocation__c> jalist = new list<sked__Job_Allocation__c>();
        list<sked__job__c> joblist = new list<sked__job__c>();
        list<sked__resource__c> resmap = new list<sked__resource__c>();

        for(sked__Job_Allocation__c ja : [select id, sked__Time_Start_Travel__c, sked__Resource__c,sked__Time_Checked_In__c,sked__Time_In_Progress__c,sked__Time_Completed__c,Resource_Type__c  
                                          from sked__Job_Allocation__c 
                                          where sked__Job__c in: jobid
                                          and sked__Resource__c in: resourceId]){
            
            for(id key : jasomap.keySet()){
                if(jasomap.get(key).Resource__c == ja.sked__Resource__c){
                    if(ja.Resource_Type__c == 'Person'){
                        ja.sked__Time_Start_Travel__c = jasomap.get(key).StartTravel__c;
                        ja.sked__Time_Checked_In__c = jasomap.get(key).FinishTravel__c;
                        ja.sked__Time_In_Progress__c = jasomap.get(key).StartJob__c;
                        ja.sked__Time_Completed__c = jasomap.get(key).FinishJob__c;
                    }
                    if(ja.Resource_Type__c == 'Asset'){
                        for(sked__job__c job : [select id, name, sked__Start__c, sked__Finish__c, sked__Duration__c from sked__job__c where id in: jobid]){
                            job.sked__Start__c = jasomap.get(key).StartJob__c;
                            job.sked__Finish__c = jasomap.get(key).FinishJob__c;
                            //Job Duration
                            if(jasomap.get(key).StartJob__c != null && jasomap.get(key).FinishJob__c != null ){
                                job.sked__Duration__c = (jasomap.get(key).FinishJob__c.getTime() - jasomap.get(key).StartJob__c.getTime()) / 60000;
                            }
                            
                            joblist.add(job);
                        }
                        for(sked__resource__c Resource : [select LatestOdometer__c from sked__resource__c where id = : ja.sked__Resource__c]){
                            resource.LatestOdometer__c = jasomap.get(key).StartOdometer__c;
                            resmap.add(resource);
                        }
                    }
                    jalist.add(ja);
                }
            }
        }
        if(jalist != null) { update jalist; }
        if(joblist != null) {update joblist;}
        if(resmap != null) {update resmap;}
        
    }

}

I don't know which part of my code I should change for this. Any help?

Thanks,

-Zach

 
Mudasir WaniMudasir Wani
The code is fine as you are not trying to update them inside For loop.
The only thing that may be causing this is the recursion.
The easiest way to do this is to create a static variable in your above class and set the variable to true and in your trigger check if that variable is set to true donot execute the code once again.
Hope this helps.

https://help.salesforce.com/apex/HTViewSolution?id=000133752&language=en_US (https://help.salesforce.com/apex/HTViewSolution?id=000133752&language=en_US)

https://help.salesforce.com/HTViewSolution?id=000002357&language=en_US (https://help.salesforce.com/HTViewSolution?id=000002357&language=en_US)

Don't forget to select best answer to make our efforts visible in the developer forum.
Please mark this as solution by selecting it as best answer if this solves your problem, So that if anyone has this issue this post can help.
Zach DelacroixZach Delacroix
Thanks for the suggestions.

@Mudasir Wani, I tried this but did not work but thanks a lot :)

@Sura, I've read that already but I am newbie and unsure how to actually follow and apply it to my code.

I'd like an answer based on experience. (visual learner here)

Thanks,

-Zach
 
Mudasir WaniMudasir Wani
Can you paste the trigger code here.
Then we can help.
Zach DelacroixZach Delacroix
Thanks!

I just simply call the Class in my Trigger. Modified it with your suggestion.
 
trigger trgJobAllocationSignOff on Job_Allocation_Sign_Off__c (
  before insert, after insert, 
  before update, after update, 
  before delete, after delete) {

  if (Trigger.isBefore) {
    if (Trigger.isInsert) {
      
    } 
    if (Trigger.isUpdate) {
        
    }
    if (Trigger.isDelete) {
      
    }
  }

  if (Trigger.IsAfter) {
    if (Trigger.isInsert) {
      
    } 
    if (Trigger.isUpdate) {
        
        if(ClsClientSignOff.runOnce()){
            ClsClientSignOff Handler = new ClsClientSignOff();
            handler.UpdateJobAllocation(Trigger.new);
        }
    }
    if (Trigger.isDelete) {
    }
  }
}

Thank you,

-Zach

 
Mudasir WaniMudasir Wani
In your class add a static variable.
 
public class ClsClientSignOff {
//Add this static variable to avoid recursive calls
public static boolean runTriggerOnlyOnce = true;

}
trigger trgJobAllocationSignOff on Job_Allocation_Sign_Off__c (
  before insert, after insert, 
  before update, after update, 
  before delete, after delete) {

  if (Trigger.isBefore) {
    if (Trigger.isInsert) {
      
    } 
    if (Trigger.isUpdate) {
        
    }
    if (Trigger.isDelete) {
      
    }
  }

  if (Trigger.IsAfter) {
    if (Trigger.isInsert) {
      
    } 
    if (Trigger.isUpdate) {
        
        if(ClsClientSignOff.runTriggerOnlyOnce == false){
            ClsClientSignOff Handler = new ClsClientSignOff();
            handler.UpdateJobAllocation(Trigger.new);
        }
    }
    if (Trigger.isDelete) {
    }
  }
}

Try this and let me know if you face the issue again.
Also I want to know how you test the functionality.
 
Zach DelacroixZach Delacroix
I've tried that earlier and still had issues with that System.LimitException: Too many DML rows: 10001.

I tested it with simply exporting all the Job_Allocation_Sign_Off__c records and then update with dataloader. I also tried it in execute anonymous..

List<Job_Allocation_Sign_Off__c> updateRecords = [select id from Job_Allocation_Sign_Off__c ];
update updateRecords;

have same error.

Thanks,

 
Mudasir WaniMudasir Wani
Hey Zach,

Use the below batch for this requirement 
global class batchJobAllocationSignOff implements Database.Batchable<sObject>
{	
	global Set<Id> JASOs;
	global batchJobAllocationSignOff(){
		// Create your JASOs id set here
		
	}
    global Database.QueryLocator start(Database.BatchableContext BC)
    {
        String query = 'select id, name, Client_Sign_Off__r.job__c, Resource__c,StartTravel__c, FinishTravel__c,StartJob__c,FinishJob__c,Resource_Type__c,StartOdometer__c, Start_Break__c, End_Break__c from Job_Allocation_Sign_Off__c where id IN : JASOs';
		//The list will be in scope variable
		return Database.getQueryLocator(query);
    }
   
    global void execute(Database.BatchableContext BC, List<Job_Allocation_Sign_Off__c> scope)
    {
        //Do the execution of your logic here 
		//The stuff you are doing in ClsClientSignOff class
    }   
    global void finish(Database.BatchableContext BC)
    {
    }
}

//Also you need to write a scheduler class for this
global class batchJobAllocationSignOffScheduler implements Schedulable{
	global void execute(SchedulableContext sc) {
		//Create a label to control the size of records processed per batch
		integer batchSize = integer.valueof(System.Label.batchJobAllocationSignOff_Size);  
    	batchJobAllocationSignOff obj = new batchJobAllocationSignOff(); 
     	database.executebatch(obj, batchSize);
  	}
}
Below is a link to a blog where you can learn about the batch
http://www.oyecode.com/2011/10/how-to-use-batch-apex-in-salesforce.html

Don't forget to select best answer to make our efforts visible in the developer forum.
Please mark this as solution by selecting it as best answer if this solves your problem, So that if anyone has this issue this post can help.
Zach DelacroixZach Delacroix
Thanks  a lot! that is a great explanation. Although I haven't tried it. I'll let you know if it works.

Thanks again! :)