+ Start a Discussion
Tobias HaggeTobias Hagge 

Help debugging: Too many DML rows: 10001

Hey, the following trigger gives me a dml exception error when uploading to production.
trigger Trigger_Account2Contact on Account (after update) {
	Account[] accounts = Trigger.New;
	Account[] oldAccounts = Trigger.Old;
	List<Account> changedAccounts = new List<Account>();
	
	for(integer i = 0; i < accounts.size(); i++)
		if(accounts[i].Customer_Process__c != oldAccounts[i].Customer_Process__c)
			changedAccounts.add(accounts[i]);
			
/* 
	if ischanged CPS = Live in Dialler: push Contact to dialler
	if ischanged CPS != Live in Dialler: Discard from dialler
*/

	Map<String, Contact> contactMap = new Map<String, Contact>();
	for(Contact c: [SELECT Id, AccountId FROM Contact WHERE Is_Applicant__c = True])
		contactMap.put(c.AccountId, c);

	for(Account account: changedAccounts)
	{
		Contact contact = contactMap.get(account.Id);
		if(contact != null)
		{		
			if(account.Customer_Process__c == '5 - Live in Dialler')
			{
				contact.Easycallnow_Table__c = 'UK: Reassessing Applications';
			}
			else
			{
				contact.Easycallnow_Table__c = null;
			}
		}
	}
	update contactMap.values();
}
Theoretical it should create a list of Accounts where the Customer_Process__c has changed and map all Contacts where Is_Applicant__c = True to it and then update a field on the Contact (Easycallnow_Table__c).

Where does it violate the governor limit? It gives the error message on every save attemp, even if Customer_Process__c is not changed at all.

Thanks for the help.
Best Answer chosen by Tobias Hagge
KaranrajKaranraj
If you look at the line number 16 you are querying the list of contact records where is_applicant__c = true and then you are storing the result in the map variable contactMap. Just igoner the line 19 to 33 whether it matched the criteria or not, at the line number you are updating all contact records which is returned in the line number 17. So you are getting the Too many DML rows: 10001  since the query is returning more than 10K records, you can't update more than 10K record in a single DML operation

To overcome this issue, try the below code approach
 
trigger Trigger_Account2Contact on Account (after update) {
	Account[] accounts = Trigger.New;
	Account[] oldAccounts = Trigger.Old;
	List<ID> changedAccountsId = new List<Id>();
	
	for(integer i = 0; i < accounts.size(); i++)
		if(accounts[i].Customer_Process__c != oldAccounts[i].Customer_Process__c)
			changedAccountsId.add(accounts[i].Id);
			
/* 
	if ischanged CPS = Live in Dialler: push Contact to dialler
	if ischanged CPS != Live in Dialler: Discard from dialler
*/

	
    List<contact> updateContact = new List<contact>();
	for(Account account: [Select id,Name,Customer_Process__c,(select ID,Easycallnow_Table__c from contacts) from Account where Id IN: changedAccountsId])
	{
        for(Contact con : account.Contacts){

            if(account.Customer_Process__c == '5 - Live in Dialler')
			{
				con.Easycallnow_Table__c = 'UK: Reassessing Applications';
			}
			else
			{
				con.Easycallnow_Table__c = null;
			}
            updateContact.add(con);
        }		
	}
	update updateContact;
}


 

All Answers

James LoghryJames Loghry

You're getting ALL applicant contacts, which apparently is > 10,000 rows.  Try limiting your SOQL query to filter on Contacts where Is_Applicant__c is true, AND the contact's AccountId is in the current trigger set.  For instance you could do something like:

for(Contact c: [SELECT Id, AccountId FROM Contact WHERE Is_Applicant__c = True And AccountId in :Trigger.newMap.keySet()])

KaranrajKaranraj
If you look at the line number 16 you are querying the list of contact records where is_applicant__c = true and then you are storing the result in the map variable contactMap. Just igoner the line 19 to 33 whether it matched the criteria or not, at the line number you are updating all contact records which is returned in the line number 17. So you are getting the Too many DML rows: 10001  since the query is returning more than 10K records, you can't update more than 10K record in a single DML operation

To overcome this issue, try the below code approach
 
trigger Trigger_Account2Contact on Account (after update) {
	Account[] accounts = Trigger.New;
	Account[] oldAccounts = Trigger.Old;
	List<ID> changedAccountsId = new List<Id>();
	
	for(integer i = 0; i < accounts.size(); i++)
		if(accounts[i].Customer_Process__c != oldAccounts[i].Customer_Process__c)
			changedAccountsId.add(accounts[i].Id);
			
/* 
	if ischanged CPS = Live in Dialler: push Contact to dialler
	if ischanged CPS != Live in Dialler: Discard from dialler
*/

	
    List<contact> updateContact = new List<contact>();
	for(Account account: [Select id,Name,Customer_Process__c,(select ID,Easycallnow_Table__c from contacts) from Account where Id IN: changedAccountsId])
	{
        for(Contact con : account.Contacts){

            if(account.Customer_Process__c == '5 - Live in Dialler')
			{
				con.Easycallnow_Table__c = 'UK: Reassessing Applications';
			}
			else
			{
				con.Easycallnow_Table__c = null;
			}
            updateContact.add(con);
        }		
	}
	update updateContact;
}


 
This was selected as the best answer