+ Start a Discussion
EnthEnth 

DML Rows Governor Limits Query/Workaround & Warning

Came across an interesting problem today where one of our bulk triggers failed due to a Too Many DML Rows limit exception.

 

We have a custom object (Order__c) with a child object (Order_Line__c).

We have a trigger on the Order to automatically create Order_Line__c records whenever a new Order is created. However, when the number of line items exceeds 100 our trigger fails BUT ONLY WHEN INVOKED VIA A STANDARD page, our unit tests work fine and if we VF the New Order page it works fine:

 

e.g.

 

 

trigger trg_ai_Order on eclone__Order__c (after insert) {
	
	List<Order_Line__c> items = new List<Order_Line__c>();
	
	for (Order__c o : trigger.new) {
		// This is just an example to demonstrate the issue
		for (Integer i=0; i<101; i++) {
			Order_Line__c oi = new Order_Line__c();
			oi.Order_No__c = o.Id;
			items.add(oi);
		}
				
	}
	
	// Insert the items
	insert items;

}

Add a new Order using the standard tab for Order gives:

 

Error: Invalid Data. 
Review all error messages below to correct your data.
Apex trigger eclone.trg_ai_Order caused an unexpected exception, contact your administrator: eclone.trg_ai_Order: System.LimitException: eclone:Too many DML rows: 101

 Whereas the following anonymous apex works fine (as the limit is 10,000):

 

Order__c o = new Order__c();
insert o;

 

 

 

And creating a Visualforce page with just the standardcontroller works fine too (an easy workaround).

 

Now I can see from the Apex Developers guide there's different limits for the Trigger and Apex and thinking about it I see that the Unit Test etc have a different entry point, hence why the different limit applies, but this seems to invalidate all our bulk trigger unit tests!

 

What's everyone else's experience of this, do you revert to Asynchrous apex instead, or Visualforce your pages ?

JA-DevJA-Dev

I haven't worked with triggers in a while, but couldn't you check the size of items before you add oi to the list and update if size = 100? Something like:

 

 

List<Order_Line__c> items = new List<Order_Line__c>();
	
for (Order__c o : trigger.new) {
    // This is just an example to demonstrate the issue
    for (Integer i=0; i<101; i++) {
        Order_Line__c oi = new Order_Line__c();
	oi.Order_No__c = o.Id;
        if (items.size() < 100)
	    items.add(oi);
        else if (items.size() == 100) {
            insert items;
            // clear the list after insertion
            items = new List<Order_Line__c>();
        }
    }			
}
	
// Insert the items
if (items.size() > 0)
    insert items;

 

Another thing you have to check is the number of DML statements that you're making (I believe is 20 for triggers). So before you call the insert statement, you should check the number of DML calls you've made so far by using Limits.getDmlStatements().

 

EnthEnth

No that won't make any difference. The governor limit applies from the start of the entry point, so even if you have the dml rows across separate insert calls, or even spread across apex classes, the limit applies from the start of the trigger.

 

The only workaround seems to be to ensure the entry point starts before the trigger (such as using a VF page), so that the higher governor limit of 10k rows applies.

 

Given the amount of time we spend preaching to use bulk inserts I would have thought SFDC should consider raising the limit from the meagre 100 (per trigger row).