+ Start a Discussion
Roger WickiRoger Wicki 

Database.update() throws dml exception

Hi Community

I am new to using Database.update() method and I thought that using the Database class would not throw any kind of Exceptions. I use this as my source information:
https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/langCon_apex_dml_database.htm
@TestVisible private void updateExistingOpportunities() {
	list<Database.SaveResult> results = Database.update(existingOpportunityMap.values());
	String errorMessage = '';
	for ( Integer i = 0; i < results.size(); i++ ) {
		if ( !results.get(i).isSuccess() ) {
			if ( errorMessage.equals('') ) {
				errorMessage = 'Following Opportunities have failed during the update:\n\n';
			}
			errorMessage += existingOpportunityMap.values().get(i).Name;
			errorMessage += '\n';
			errorMessage += 'https://eu4.salesforce.com/';
			errorMessage += existingOpportunityMap.values().get(i).Id;
			errorMessage += 'Errors:\n';
			for ( Database.Error theError : results.get(i).getErrors() ) {
				errorMessage += theError.getStatusCode();
				errorMessage += '\n';
				errorMessage += theError.getMessage();
			}
		}
	}
}
The above is my method I like to test. I want to force running through the result loop with an error so i get maximum code coverage and see that the output is as I desired it. I tried it with an inserted Opportunity of which I tried putting the CloseDate on null. But this throws a DML Exception. I thought I would not get any exceptions, but be able to read out the Database.result...

Any hints on that?
Best Answer chosen by Roger Wicki
LizzyLizzy
Hi Roger,

I think your question may actually be answered in the link you provided:
"One difference between the two options is that by using the Database class method, you can specify whether or not to allow for partial record processing if errors are encountered. You can do so by passing an additional second Boolean parameter. If you specify false for this parameter and if a record fails, the remainder of DML operations can still succeed. Also, instead of exceptions, a result object array (or one result object if only one sObject was passed in) is returned containing the status of each operation and any errors encountered. By default, this optional parameter is true, which means that if at least one sObject can’t be processed, all remaining sObjects won’t and an exception will be thrown for the record that causes a failure."
When you call Database.update(), you need to pass in a second parameter, false, which allows for partial processing and returns an array of result objects. If you don't pass this second parameter, it defaults to true, and if any object errors an exception gets thrown.

I think if you change
list<Database.SaveResult> results = Database.update(existingOpportunityMap.values());

to 
list<Database.SaveResult> results = Database.update(existingOpportunityMap.values(), false);

that might solve your issue.

Hope this helps!

Lizzy

All Answers

LizzyLizzy
Hi Roger,

I think your question may actually be answered in the link you provided:
"One difference between the two options is that by using the Database class method, you can specify whether or not to allow for partial record processing if errors are encountered. You can do so by passing an additional second Boolean parameter. If you specify false for this parameter and if a record fails, the remainder of DML operations can still succeed. Also, instead of exceptions, a result object array (or one result object if only one sObject was passed in) is returned containing the status of each operation and any errors encountered. By default, this optional parameter is true, which means that if at least one sObject can’t be processed, all remaining sObjects won’t and an exception will be thrown for the record that causes a failure."
When you call Database.update(), you need to pass in a second parameter, false, which allows for partial processing and returns an array of result objects. If you don't pass this second parameter, it defaults to true, and if any object errors an exception gets thrown.

I think if you change
list<Database.SaveResult> results = Database.update(existingOpportunityMap.values());

to 
list<Database.SaveResult> results = Database.update(existingOpportunityMap.values(), false);

that might solve your issue.

Hope this helps!

Lizzy
This was selected as the best answer
Roger WickiRoger Wicki
Hi Lizzy

Thanks. But I think that's confusing.... So if I change it to false, it will not throw exceptions but display error information in the result array? Got to try that.
Roger WickiRoger Wicki
Hey Lizzy

Thanks for your help, that actually did it. Either I am really bad at understanding the docs or this disambiguition is not well stated. So a Database.update(list<sObject>, true) is actually the very same as the update list<sObject> in the end.
LizzyLizzy
Hi Roger,

Glad that worked!

I do see your confusion, it seems odd to have two methods that effectively do the same thing. There are other parameters you can add to database.update() (https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_methods_system_database.htm#apex_System_Database_update_3) which allter different aspects of behaviour, but just calling Database.update(list<sObject>, true) is as you say effectively the same as calling the update DML statement.