Salesforce documentation says
- "Total number of records processed as a result of DML statements, Approval.process, or database.emptyRecycleBin is 10,000"
- "Total number of DML statements issued 150"
It does not mean you can delete/insert/update/upsert a row maximum of 9999 in a group up to 150 times. It is cumulative that mean the number of records gets added as a single list. Which means as soon you start your DML process or enter inside your apex function your session starts and then with each DML it keeps adding rows to check the count is less than 10,000 or not.
For Example:
public void delTest(){
List<Account> a; // say of size 9000
List<Account__c> a1; // Say list of 2000;
// Now if we fire
delete a;
delete a1;
// We are going to receive too many DML rows as the total count of DML rows is
// 9000 + 2000 = 11,000.
}
To overcome this issue we have two possible solution
- To implement a batch/future/remote [asynchronous] process to delete
- Or we need to check the total size of the DML rows and go back to the VF page and initiate same function until all desired record got deleted.
But if we want synchronous operation actionFunction is the only operation which can help up to do more DML.
<apex:page>
<apex:form>
<apex:actionFunction name="delTest" action="{!delTest}" rerender="scriptPanel" onComplete="CheckAllDone();" />
<apex:actionFunction name="allDone" action="{!allDone}" rerender="page" />
</apex:form>
<apex:outputPanel id="scriptPanel" >
<script>
function CheckAllDone(){
var hasMore = {!hasMore} ;
if(hasMore){
delTest();
}
else{
allDone();
}
}
</script>
<apex:outputPanel/>
</apex:page>
public Boolean allDone {get;set;} {allDone = false; }
public Boolean hasMore {get;set;} {hasMore =false; }
public void delTest(){
allDone = false;
hasMore = false;
List<Account> a; // SOQL to get records
List<Account__c> a1; // SOQL to get records
List<sObject> objList = new List<sObject>();
for(Account temp : a){
if(objList.size() >= 9999){
hasMore = true;
break;
}
objList.add(temp);
}
for(Account__c temp : a1){
if(objList.size() >= 9999){
hasMore = true;
break;
}
objList.add(temp);
}
// do check for sizes here if size > 10,000 limit the DML and prepare batches
delete objList;
if(hasMore == false){
allDone = true;
}
}
public void allDone(){
// do nothing;
}
//====================== batch Class ===========================
global class BatchDelete implements Database.Batchable<sObject>,Database.Stateful{
// to remember List Of dml rows.
global Set<Id> sobjList = new Set<Id>();
global Boolean allDone = false;
// constructor
global BatchDelete (){
}
global Database.QueryLocator start(Database.BatchableContext batchContext) {
// do sqol to get data
String query = 'Your SOQL here';
return Database.getQueryLocator(query);
}
global void execute(Database.BatchableContext BC, list<sObject> forDML){
// add here and manipulate your dmlList.
// add to the set sobjList
// set allDone to true if all dml completed
}
global void finish(Database.BatchableContext BC){
// chain the batch job
if(!allDone){
Database.executeBatch(this);
}
else{
// fire a trigger or email to start another process.
}
}
}
Is there any special need to use two list a and a1?
ReplyDeleteYes there is a limit on number of DML rows.
Delete