2

I came across two methods of preventing errors while inserting, updating or deleting the records in salesforce. Let's say I am performing any one DML operation, and I want the transaction to stop if any error occurs.

  • Should I use sObject.addError() to throw an error and stop the execution of DML? As per documentation, this will prevent any DML operation from executing. Does that mean after the error, my database will be in the same state as it was before trigger execution?
  • If I use savepoints and rollbacks in the trigger, what advantage would it have over the first approach?
  • If I use Database.insert(listOfRecords, true), this will also prevent partial insertion of records. So what difference would it make over the above two approaches?

In which scenarios would we use each one of them? Any explanation is much appreciated.

2

Should I use sObject.addError() to throw an error and stop the execution of DML? As per documentation, this will prevent any DML operation from executing. Does that mean after the error, my database will be in the same state as it was before trigger execution?

This method will only mark some records as in error. What this actually means depends on the trigger's calling context. If allOrNone is true, then the entire transaction rolls back. Otherwise, a second attempt is made on any records not flagged with an error, allow a partial update to potentially succeed. If the DML operation fails, the state of the database is unchanged.

If I use savepoints and rollbacks in the trigger, what advantage would it have over the first approach?

You should never use this in a trigger. Simply call addError on records which should display an error and let the framework handle the result for you. The use of rollback is for atomic updates. For example:

SavePoint sp = Database.setSavePoint();
try {
  update accounts;
  update opportunities;
  update contacts;
  insert opportunityContactRoles;
} catch(DmlException e) {
  Database.rollback(sp);
  // Show an error to a user
}

This should only be used in Apex methods that will return a value to a Visualforce page or Lightning component. It should not be used in a trigger context.

In a trigger, the only truly acceptable method is addError. This is because it allows bulk updates to succeed without having to "guess" which record was in error.

Have you ever uploaded records in the Data Loader? Notice how just one record can fail, but the remaining succeed? This is normally desirable behavior when the records being processed are unrelated, but happen to be in the same bulk upload. Not using addError properly disables this behavior and causes confusing errors (such as 200 records in a block all showing the same error).

Note that addError implies a rollback. For the retry mechanism, the governor limits are reset back to before the trigger was called, the database is rewound back to that point (as a rollback would do), and a second attempt is made with the remaining records, if any.

If I use Database.insert(listOfRecords, true), this will also prevent partial insertion of records. So what difference would it make over the above two approaches?

That only prevents the downstream operations from partially succeeding. AddError propagates the error upstream towards the caller. You should never use allOrNone in a trigger. Use allOrNone set to false, and add an error (addError) to the failing record. This allows the upstream caller to determine if partial success is acceptable.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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