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
Tony Williams 9Tony Williams 9 

DML Limit 10000 Reached While Processing 9455 Account Team Objects

HI I am running a batch scirpt that has up to 9455 accounts. I need to update their acoucnt objects. The problem is that I have code that has to insert 3 Account Team Members per each Account record that is being iterated or 3 DML * 9455 = 28.365K.  The Account Team Objects being updated don;t have any triggers that do any firing.
Q) How can I avoid this "DML Limit  of 10000"  issue? 
Q) Should I increasemy batch limit?  Currently this is what I am using: Database.executeBatch(job, 10);
Here is the code and Thanks.:
BATCH:
===================================================================
global class BatchUpdateAccountTeams  implements Database.Batchable<sObject>,Database.AllowsCallouts, Database.Stateful {
     global String query;
    global Integer accountSize = 0;
    List<Account> accountsToUpdate = new List<Account>();
    global class UtilException extends Exception {} 
    
    
    global database.querylocator start(Database.BatchableContext BC){
        //*****************************************************************************************************************************************************************************p
        //Select All active US Accounts that have counties and states
        //NOTE: You don't need to get all Physical address components just the city and state.
        //*****************************************************************************************************************************************************************************
        if(query == null) 
        {
        query 
            = 'Select Id,Mailing_Address_Book__c,Physical_County__c,Physical_State__c  '
            + ' From Account WHERE Status__c = \'Added\' '
            + ' And Physical_County__c <> null '
            + ' And Physical_State__c <> null '
            + ' And Registration_Level__c = \'R1\''
            + ' And Type = \'Church\''
            + ' And RecordType.Name like \'%US Organization%\' limit 10000';
        }
        system.debug('<< QUERY  >> '+query);  
        return Database.getQueryLocator(query);
    }
    
    global void execute(Database.BatchableContext BC, List<sObject> scope){
        
        List<Id> accountIDs = new List<Id>();
        //List<RecordType> rec = [Select Id from RecordType where Name = 'US Organization' Limit 1];
        //1. Get access to all Active US Organizations having Physical counties and states.
        for(sObject s : scope){
          Account thisAccount = (Account)s;
            accountsToUpdate.add(thisAccount);
            accountIDs.add(thisAccount.Id);
            accountSize++;
        }
    //accountSize = accountsToUpdate.size();
    system.debug('<< Max Accounts found>> '+accountSize);
        //2. Update The Account Teams for these accounts with the most recent account team personnel including VP of US Missionaries
        if(accountsToUpdate.size() > 0){
          TeamMemberAccounts.handler(accountsToUpdate,accountIDs); 
            TeamMemberAccounts.handler(accountsToUpdate); 
        }
    }
    
  global void finish(Database.BatchableContext BC){
        List<Messaging.SingleEmailMessage> emailList = new List<Messaging.SingleEmailMessage>();
      Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
         //Send email to all in Account Teams Updates Group if any account team member objects were created/updated
        if(accountSize > 0){
            //3. Get User Ids for the Acocunt Team Updates Group.
            Map<Id,User> users = new Map<Id, User>([SELECT Id, Email FROM User WHERE Id IN (
                    SELECT UserOrGroupId FROM GroupMember WHERE Group.Name = 'Account Team Updates')]);
            
          
            List<String> userEmail = new List<String>();
            //We need to make sure that the Test coverage will work when testing emails otherwise a REQUIRED_FIELD_MISSING, Missing exception will occur.
            if(Test.isRunningTest()){
                User tUser=[Select Email from User where Name Like 'MyAwana%' Limit 1];
                userEmail.add(tUser.Email);
            }else{
               for(User someUser : users.values()){
          userEmail.add(someUser.Email); 
              }
            }
            List<String> sendTo = new List<String>();
      sendTo.addAll(userEmail);
      //4. Assign the addresses for the To and CC lists to the mail object.
          mail.setToAddresses(sendTo);            // Specify the subject line for your email address.
           //5. Set to True if you want to BCC yourself on the email.
          mail.setBccSender(false);
      //6.: Set who the email is sent from
          mail.setReplyTo('noreply@awana.org');
          mail.setSenderDisplayName('No Reply');
      //7. Set email contents !
          mail.setSubject('Accounts Process with Updated or New  Account Teams');
            String lines = '<br>';
            Integer lineCounter = 0;
            Integer lineLimit = 20;
            for(Account an_account : accountsToUpdate){
                lines = lines+an_account.Mailing_Address_Book__c+', ';
               lineCounter++;  
                if(lineCounter == lineLimit - 1){
                   lines = lines+'<br>'; 
                }
                if(lineCounter == lineLimit){
                   lineCounter=0; 
                }
            }//loop
            system.debug('<<LINES>> '+lines);
          mail.setHtmlbody('Total Accounts Processed:<b> '+ accountSize+'</b><br>'+lines+'</b><br>');
            // Send the email you have created.' '+
            emailList.add(mail);
      Messaging.sendEmail(emailList);
        }
  }
    
}
====================== TEAM MEMBER ACCOUNTS.CLS==================
public with sharing class TeamMemberAccounts { 
    /* 
     * Method:  handleOpportunityInsert
     * Inputs:  List of Accounts which have ownership updates to be matched with their ATMs (Account Team Member)
     * Purpose: To verify that we will have a State Director whether due to updating the ATM or creating a new one.
     * SOQL:    1
     * DML:     2
     */
  public class handlerException extends Exception{} 
/***************************************************************************************************************************************************
   Method: handler: Makes sure that Primary Missionaries are assigned as Account Team Memebrs programmatically
****************************************************************************************************************************************************/
    public static void handler(List<Account> Accts,List<ID> acctIDS){
        List<AccountTeamMember> insert_ATM_FieldDirs = new List<AccountTeamMember>();
        List<AccountTeamMember> insert_ATM_WGroupLdrs = new List<AccountTeamMember>(); 
        List<AccountTeamMember> insert_ATM_PMissions = new List<AccountTeamMember>();  
        List<Id> ownerIDs = new List<Id>();
        Boolean foundStateDir = false;
        // Old ATM Roles must go because we don't know how if these users are still available.
       List<AccountTeamMember> delete_ATMS = [Select AccountID,UserId,TeamMemberRole from AccountTeamMember  WHERE TeamMemberRole in ('Field Director','Work Group Leader','Primary Missionary')  and AccountId in : acctIDs];
       if(delete_ATMS.size() > 0){ 
            delete delete_ATMS;
        }
        
        system.debug('<<NUMBER OF QUERIES In TOTAL : '+Limits.getLimitQueries());
        
        //For each account selected go and get the Account Team Mebmers while  updating the account owner.
       List<US_Counties__c> uscs = [Select Name,State_Name__c,Field_Director__c, Work_Group_Leader__c, Primary_Missionary__c from US_Counties__c  ORDER BY State_Name__c, Name Asc];

		Map<String,List<US_Counties__c>> usCounties = new Map<String,List<US_Counties__c>>();

		for(US_Counties__c usc : uscs){
			if(!usCounties.containsKey(usc.Name)){
				usCounties.put(usc.Name,new List<US_Counties__c>());
			}
			usCounties.get(usc.Name).add(usc);
		}

		for(Account a: Accts){
			if(usCounties.containsKey(a.Physical_County__c)){
				for(US_Counties__c a_county : usCounties.get(a.Physical_County__c)){
					if(a_county.State_Name__c == a.Physical_State__c){
						insert_ATM_FieldDirs.add(new AccountTeamMember(UserId=a_county.Field_Director__c, AccountId=a.Id,TeamMemberRole='Field Director')); 
						insert_ATM_WGroupLdrs.add(new AccountTeamMember(UserId=a_county.Work_Group_Leader__c, AccountId=a.Id,TeamMemberRole='Work Group Leader'));
						insert_ATM_PMissions.add(new AccountTeamMember(UserId=a_county.Primary_Missionary__c, AccountId=a.Id,TeamMemberRole='Primary Missionary'));
						ownerIDS.add(a_county.Primary_Missionary__c);
						break;
					}
				}
			}
		}
    
    //5.  Insert all Permission Set Assignments for Account Health  Permissionset using Future Method... this is a Setup DML object
    if(ownerIDs.size() > 0){
        accountHealthAccessHandler(ownerIDs);
    }
    //6. - Insert All ATMs
   
    if(insert_ATM_FieldDirs.size() > 0){ 
        Database.UpsertResult[] lsr = Database.upsert(insert_ATM_FieldDirs,false);
    }
    if(insert_ATM_WGroupLdrs.size() > 0){ 
        Database.SaveResult[] lsr = Database.insert(insert_ATM_WGroupLdrs,false);
    }
    
     if(insert_ATM_PMissions.size() > 0){ 
        Database.SaveResult[] lsr = Database.insert(insert_ATM_PMissions,false);
    }
    
    
    system.debug('ATMS FOR INSERTED State Dirs: '+insert_ATM_FieldDirs);
    system.debug('ATMS FOR INSERTED Work Group Leaders: '+insert_ATM_WGroupLdrs);
    system.debug('ATMS FOR INSERTED Primary Missionaries: '+insert_ATM_PMissions);
    }//Handler 1
   
/***************************************************************************************************************************************************
   Method: handler: VP for US Missionaries handler: Simply adds an ATM team role for VPs
****************************************************************************************************************************************************/
    public static void handler(List<Account> newAccts){
        system.debug('<<INSIDE VP Of US Missionaries Handler >> '+newAccts);
        List<AccountTeamMember> insert_ATM_VPs = new List<AccountTeamMember>();
        List<GroupMember> vpUser = [Select UserOrGroupId From GroupMember where Group.Name = 'VP of Account Team' limit 1];
        for(Account someAccount : newAccts){
            insert_ATM_VPs.add(new AccountTeamMember(UserId=vpUser[0].UserOrGroupId, AccountId=someAccount.Id,TeamMemberRole='VP of US Missionaries'));   
        }
        if(insert_ATM_VPs.size() > 0){ 
            Database.SaveResult[] lsr = Database.insert(insert_ATM_VPs,false);
        }
    }// Handler 2
/***************************************************************************************************************************************************
   Method: accountHealthAccessHandler: Future Method for Setup DML so that Permission Set Account Health Access can be given to new account members
****************************************************************************************************************************************************/
  
  //@future
  public static void accountHealthAccessHandler(List<Id> ownerIDs){
    PermissionSet pset = [Select Id From PermissionSet where name = 'Account_Health_Access' limit 1];
    List<PermissionSetAssignment> account_health_access = new List<PermissionSetAssignment>();
    Map<Id,String> filteredOutIDs = new Map<Id,String>();
    for(PermissionSetAssignment dupePSAs : [Select AssigneeId from PermissionSetAssignment where PermissionSet.Name ='Account_Health_Access' and AssigneeId in: ownerIDs] ){
        filteredOutIDs.put(dupePSAs.AssigneeId,'Account Health Access'); // Strain out unecessary owners if they already have this Health Account Permission. Example: State Director is account owner again replacing Prime Missionary
    }// Loop
    system.debug('<< OWNER LIST>> '+ownerIDs);
    for(Id someOwnerId : ownerIDs){
        if('Account Health Access' != filteredOutIDs.get(someOwnerId)){
            account_health_access.add(new PermissionSetAssignment(AssigneeId = someOwnerId, PermissionSetId=pset.Id));
        }
    }//Loop
    system.debug('<< ACCT HEALTH SIZE>> '+account_health_access.size());
    if(account_health_access.size() > 0){
        insert account_health_access;
    }
  }
}//Class

 
Tony Williams 9Tony Williams 9
I solved this. 
  1. I had to create within the back a limit which would only process 1000 records at a time out of 9K accont records.  To compound th issue I had 5 DML statements. 
  2. I then created a batchable job size of 1000 Database.executeBatch(ord , 1000);