Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm working on a cleanup of some older apex code, and I've noticed two distinct patterns being used to handle errors when saving records.

One uses a try-catch block to try to update the records, and displays the exception to the page if any is caught.

try {
    update accounts;
} catch (Exception e) {
    ApexPages.addMessages(e);
}

The other uses the Database class to get a result, and then iterates over the results of a insert/update operation and displays the error onto the page.

Database.SaveResult result = Database.Update(accounts, true); 

if (!result.isSuccess()) {
    for (Database.Error err:result.getErrors()) {
        ApexPages.addMessage(new ApexPages.message(ApexPages.Severity.ERROR, err.getMessage()));
    }
}

Which of these two patterns is more efficient?

share|improve this question
2  
efficient in which terms? – AtulRajguru9 Mar 2 at 15:03
2  
I only use Database.Update with allOrNothing = false when I'm allowing for partial successes; otherwise I use the try-catch – cropredy Mar 2 at 17:26
up vote 7 down vote accepted

I wouldn't necessarily say that one is more "efficient" than the other. It's more a matter of what the author wanted the code to accomplish. The first method will only add one message to send to a page while the latter will add a message for each record that isn't saved.

What do you want to accomplish with your code and convey to the user? Is your code in a trigger, a class of some kind, or is it in a controller for a visualforce page? The location of the code would impact the choice one might make. I don't believe the answer to your question is merely one of efficiency.

share|improve this answer
    
Ive heard that using a try/catch can be more expensive than other methods, which led me to asking this question. The code itself is a controller for a visualforce page, as the goal of these snippets, as far as I understand the author's intent, was merely to get the message onto the page as quickly as possible. I guess the question would come down to "Should I use a try/catch or not?". – battery.cord Mar 2 at 15:17
1  
@battery.cord Unless you're working with very large datasets, which is hard to do through a Visualforce page, it's unlikely that there'd be any difference in execution time. Using the database methods for DML with the second parameter AllOrNone set to true (and passing a list of sobjects) means that it won't suppress any exceptions...which would lead to needing to use try/catch anyway. tl;dr just use try/catch – Derek F Mar 2 at 15:26
1  
If you use the database result method, a try-catch method isn't necessary. I don't know that a try-catch is "more expensive". You'd have to be more specific in telling us what "expensive" means to you. I can't see where one would be slower than the other unless it's an extremely large save with a lot of errors being sent to the page. Even then, the difference in page load would seem to be miniscule unlss you exceeded the viewstate limits and likely overwhelm the viewer with the error messages. – crmprogdev Mar 2 at 15:28
2  
Agreed with the general sentiment in the comments. SFDC is slow and inefficient to begin with. Optimizing on ms doesn't really do much. The biggest culprits for inefficiencies can be found in googling best practices. Stay away from the biggest inefficiencies and then you can just focus on logic. So I 2nd @crmprogdev, its all a matter of what you want to accomplish. – Chris Fellows Mar 2 at 19:27
2  
ApexPages.addMessages can add many messages - see example in my answer. – Keith C Mar 2 at 19:59

In addition to the addMessages I also create an exception record, because if It isn't an error that should be a hard stop I still may want to know what broke. This requires a new custom object, I call it Exception

public with sharing class BusinessException extends Exception
{
public static void recordError(String fileName, String methodName, String errorMessage)
{
        Exceptions__c newException = createError(fileName, methodName, errorMessage);
        insertError(newException);          
 }

private static Exceptions__c createError(String fileName, String methodName, String errorMessage)
{
    Exceptions__c result = new Exceptions__c();
    result.FileName__c = fileName;
    result.MethodName__c = methodName;
    result.SystemError__c = errorMessage;

    return result;
}

private static void insertError(Exceptions__c oopsey)
{
    try
    {
        insert oopsey;
    }
    catch(DMLException dmlError)
    {

    }
   }
}

Then when you build your Try/Catch, whatever what you decide on you can capture that failure in your new object. I do a ton of Callouts and would be lost without this pattern

 try
    {     
       //something      
    }
    catch(QueryException error)
    {

        BusinessException .recordError('File_Name', 'Method Name', error);
    }   
share|improve this answer
4  
Plural object names! Boo! Still +1 for the logging concept. – Adrian Larson Mar 2 at 19:17
    
I actually do something very similar, which has helped greatly in tracking down some of the rarer exceptions that crop up from time to time. – battery.cord Mar 3 at 14:51
    
Instead of DML I go for Database.insert(OopseyList, false) in the insertError method – Bennie Mar 3 at 18:24
    
Can we bulkify this one? Such that recordError is called without an Insert call and insertError is called at the end of each class and trigger. – Bennie Mar 4 at 13:59

This test page:

<apex:page controller="MyController">
    <apex:pageMessages/>
    <apex:form>
        <apex:commandButton value="Save" action="{!save}"/>
    </apex:form>
</apex:page> 

and controller:

public with sharing class MyController {
    public PageReference save() {
        try {
            insert new Contact[] {
                    new Contact(),
                    new Contact(),
                    new Contact(Phone = '12345678901234567890123456789012345678901234567890'),
                    new Contact(Birthdate = Date.newInstance(1, 1, 0)),
                    new Contact(Birthdate = Date.newInstance(1, 1, 0)),
                    new Contact(AssistantName = 'ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ')
                    };
        } catch (DmlException e) {
            ApexPages.addMessages(e);
        }
        return null;
    }
}

produces this result:

screen shot of multiple messages

So as the plural addMessages method name hints the try/catch/ApexPages.addMessages does a good job of capturing the important information when there are multiple errors.

In terms of efficiency, it is a simple pattern to code correctly so it is efficient in that sense.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.