1

I added a static variable named, "firstcall" to my method that gets called from a trigger. Static Boolean firstcall = false;. That variable is originally set to false but when the method runs it checks it and if false, runs the code. The code then updates this static variable to true. My intention was to prevent it from re-running if it gets called by an update in the same execution context (meaning a field update causes the trigger to fire again when I really don't want that)

If I use execute anonymous to insert 225 records on this object, the method only runs on the first 200.

The trigger fires for each batch.. so the last 25 records is not getting updated. Is there a way I can allow the bulk records to be updated but still add the check?

Any input would be greatly appreciated!

4
  • One approach is to build a set of Id values and only run once for each Id, but that will only work in after triggers where the Id values are defined.
    – Keith C
    Commented Aug 12, 2019 at 16:07
  • Thanks Keith! This would also need to be included in insert. I appreciate your input!
    – Frank
    Commented Aug 12, 2019 at 16:14
  • You can use the record index for the insert case but that is a bit ugly. Best see if anyone has a better approach.
    – Keith C
    Commented Aug 12, 2019 at 16:16
  • Thanks again Keith! Hopefully, someone has some insight on how to make this work. thanks again!
    – Frank
    Commented Aug 12, 2019 at 16:36

1 Answer 1

0

This is a common mistake - using a single static boolean to control recursion - it will generally work OK if the transaction size is <= 200 records but there are use cases when the transaction size will be greater than 200:

  • Bulk API
  • Platform Event triggers
  • DML of some list of objects, size > 200 such as your execute anon

To control recursion it is best to remember the Ids in a static set and check the set membership before processing the sobject. This obviously works only after insert, before/after update.

Alternatively, make the code logic immune from doing double work, even if presented with the same object again (by checking sobject field values).

Now, when using static variables, there is a special case to consider which has to do with partial successes on an allOrNone=false Database.update or Database.insert operation. SFDC will automatically retry the partial successes but won't clear the static variable on the retry. So, if your method is, say, trying to do callouts, the recursion control will prevent the callouts from happening on the partial success retry. And the callouts will never happen! (This can arise in API calls to your org where the DmlOptions are set to AllOrNone=false)

When a DML call is made with partial success allowed, more than one attempt can be made to save the successful records if the initial attempt results in errors for some records. For example, an error can occur for a record when a user-validation rule fails. Triggers are fired during the first attempt and are fired again during subsequent attempts. Because these trigger invocations are part of the same transaction, static class variables that are accessed by the trigger aren't reset. DML calls allow partial success when you set the allOrNone parameter of a Database DML method to false or when you call the SOAP API with default settings. For more details, see Bulk DML Exception Handling.

See this answer for a workaround or this lengthy blog post for more explication

1
  • Thanks for the detailed explanation cropredy!!!
    – Frank
    Commented Aug 19, 2019 at 15:17

You must log in to answer this question.

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