0

i read the steps of execution flow in saleaforce but i am new to salesforce so have confusion at some points. If I have inserted batch of records and i have a after trigger on the same object, which inturns inserts records of its child object. For example if i insert records through data loader, even if few records fails, rest will insert. At the same time if in my trigger i use database.insert true, then will my child records insert? If there are failures in mu inserted parent records??? If no, then how come parent records are inserted via data loader and not child records? Any help is greatly appreciated

1

It depends on how your code was written. If you don't handle errors properly, then it's possible for your trigger to fail that way. For this reason, you should never use the following type of code:

try {
  database.insert(records, true);
} catch(Exception e) {
  System.debug(e.getMessage());
}

This is probably the number one mistake of new Apex Code developers. If you've already fallen for that trap, it's time to stop. There's a few proper ways to do this, but I find that the best way to do so is to report any child errors back to the parent record.

This is the framework that I always prefer to use in triggers:

SObject[] source = new SObject[0], newRecords = new SObject[0];
for(SObject record: Trigger.new) {
  // do some logic involving adding records
  // NOTE: for each record added to newRecords, add the source record again.
  source.add(record);
  newRecords.add(new SObject(...));
}
Database.SaveResult[] results = Database.insert(newRecords, false);
for(Integer i = 0, s = source.size(); i < s; i++) {
  if(!results[i].isSuccess()) {
    source[i].addError('Failed to create child record. The first error was: '+results[i].getErrors()[0].getMessage());
  }
}

You don't need to do anything special like rolling back records or anything, because the framework will take care of that for you. The exact behavior depends on the calling context; it will throw an exception when allOrNone is true, and it will go through the retry logic when allOrNone is false.

The retry logic tries to perform the DML operation. If any errors are generated, those records are set aside, the database is rolled back, and a second attempt is made on the remaining records. Should any errors come up again, the database will repeat the process once more, and finally give up. You can read more about it in the Bulk DML Exception Handling.

As a best practice, you should almost always consider leveraging the retry mechanism while in a trigger context. This will make your system a lot less frustrating when you need to bulk-load records.

Note that the above code is obviously generic, replace SObject with the appropriate type(s) that you're working with.

| improve this answer | |
  • Hi sfdcfox ,thanks for your above response. I understand that trigger is fired again on remaining records in the second attempt.. But here i am running in to issues when trigger is fired for the second time..... Here is what is hapening, i am calling a method from trigger to create child records when a particular field is updated on its parent record. I used static variable to prevent recursion. But here when trigger is fired again for second attempt, my static variable is not reset and trigger is not calling method in second attempt and hence child records are not created. Pls help – user59223 Aug 20 '18 at 17:26
  • @user59223 yes, using the "runOnce" technique is a bad idea. I'm not sure who started it, or who made it popular, but it's a broken technique to be sure. I demonstrate one framework that is at least marginally better. You should set the recursive flag at the start of a trigger event and unset it at the end, to allow for the possibility of retries, batches of more than 200 records, etc. – sfdcfox Aug 20 '18 at 17:42

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.