2

I'm trying to write a trigger and having some real trouble in making it work.

Background: we adopted the Country/State picklist "Feature" last year. All the cleanup wasn't done. We have some records that currently violate the validation rule.

Trigger: my trigger is one that updates a contact when it's lookup account is changed. Basically, I have a field on the account and contact that mirrors, with the one at the account level taking prescedence. (Trigger on Account (after insert, after update))

Problem: If the contact has invalid country/state values, then the field validation exception is thrown when using DML statement.

update accounts;

This isn't a problem for one-offs, but has obvious problems during bulk update/insert.

Question: So, I've decided to allow a partial update. Here's the code (pretty boiler plate from what I've seen):

    Database.SaveResult[] lsr = Database.update(updateContacts, false);  
 for(Database.SaveResult sr : lsr){
    if (!sr.isSuccess()) {
        for(Database.Error err : sr.getErrors()) 
        {
            System.debug('The following error has occurred' + sr.getId());               
            System.debug(err.getStatusCode() + ': ' + err.getMessage());
            System.debug('Account fields that affected this error: ' + err.getFields());
        }
    } 
}

Now, when I implement this, the field validation exception is no longer thrown (or is handled somehow) and all the records update without fail.

Does this sound right? Is there a way that the database class somehow avoids the validation error that dml statements are subject to?

Any advice would be helpful. Thanks in advance.

1
  • With the above method, not all contacts are guaranteed to be updated when you update their parent. Why don't you just turn off the validation rule if it is not according to the business rule? If you want the validation rule to be fired while record update, there is not other way than cleaning your dirty records. Mar 18, 2015 at 17:18

1 Answer 1

4

Not all records will be updated. It is a partial update. You're ignoring the errors (there's no addError function), so they silently disappear.

You'll want something like this:

Map<Id, Account> accounts = new Map<Id, Account>();
Map<Id, String> errors = new Map<Id, String>();

// Prepare data
for(Contact record: Trigger.new) {
    if(record.AccountId != null) {
        accounts.put(record.AccountId, new Account(Id=record.AccountId /* etc... */));
    }
}

// We need an ordered list
Account[] accountList = accounts.values();
Database.SaveResult[] saves = Database.update(accountList, false);

// Process errors
for(Integer index = 0; index < saves.size(); index++) {
    if(!saves[index].isSuccess()) {
        errors.put(accountList[index].Id, saves[index].getErrors()[0].getMessage());
    }
}
// Report errors to related contact
for(Contact record: Trigger.new) {
    if(errors.containsKey(record.AccountId)) {
        record.addError('Failed to update account: '+errors.get(record.AccountId));
    }
}
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .