I do not wish to paste the HUGE trigger this is related to (several hundred lines). However, a long time ago when it was first written, I believe it was MEANT to update "all accounts affected" with ONE "update" command at the end, while right now, it's executing "update" after each account (which I believe is attributing to the very limited number of records that can be touched in a single batch, between 10 and 50).
update accObj;
//updateList.add((Account)accObj);
The first line is currently executed after each Account is processed. I BELIEVE the second line was previously used to accumulate "all accounts to run update against" so that you could then "update" AFTER ALL accounts were done being touched. I cannot find reference to how I'd notate the "update" command if this is true. I am imagining it is something like:
update (updateList);
Could someone verify? I don't want to trial-and-error this, find out it sort of works, deploy it and... cause issues by virtue of an ASSumption.
Thanks.
Attribution to: AMM
Possible Suggestion/Solution #1
The normal update keyword works on lists/arrays of sObjects as well as single objects. So something as simple as:
update updateList;
Should work just fine. There's also an alternate method syntax like so:
Database.update(updateList);
This second from has some optional parameters relating to advanced DML options (not usually relevant, they control things like assignment rules) and allows allowing partial saves, but both bits of my sample code are equivalent and should behave exactly the same.
Attribution to: ca_peterson
Possible Suggestion/Solution #2
You are most likely running into governor limits as a result of including a DML statement within a loop. Currently you can issue 150 DML statement within an invocation context.
The best practices for triggers include keeping all queries and DML statements outside of any loops. Your code should only perform a query, update, etc once per invocation and should not be dependent on the number of records in your batch. (Here is a pretty good blog post ).
It looks like from the excerpt you provided that the code was originally set up to according to these best practices, but something changed over time.
List<Account> updateList = new List<account>();
for (Account accObj : UniverseOfAccounts) {
//Where UniverseOfAccounts is the list of accounts you are looping over in your trigger
if (meetsSomeCondition(accObj)) {
// you have some logic here to change some field values on the account
accObj.someField = someNewValue;
// now add it to your list to be updated outside of the loop
updateList.add(accObj);
}
}
// now perform the actual update
if(updateList.IsEmpty()==false) {
update updateList;
}
I would make sure to do some testing with real data before deploying, since I'm guessing some issue came up somewhere else in the code that caused the developer to shift from doing things the right way from a bulk perspective. Perhaps one of the records would fail in the batch due to a validation rule or some other problem and prevent all the updates from occurring? If that is the case look into some exception handling around the update (see the example at the bottom of the page for inspiration) and perhaps the optAllorNone property as a better solution than having the update within a loop.
Attribution to: Tim Watt
Possible Suggestion/Solution #3
You are correct, you can just call update with the list as a paramter:
update updateList;
And if you want to prevent one failed record from stopping all the others you want to use the Database methods (the method can fail all if you require it to do so, see the docs):
for(Database.SaveResult r = Database.update(updateList, false)
{
if(!r.isSuccess())
{
// error handling - you can use addError() to add errors to individual records
}
}
A final thing to consider is whether you need to allow for more than 200 updates. For example, if your trigger is not working on the Account object directly, you may have more than 200 accounts which need updating and this can not be done in one update. In that scenario you need to modify the code where you add the accounts to the list (I'm using the simple style update for brevity):
for(Account accOjb : <<some account collection>>)
{
// inside a loop
updateList.add(accObj);
if(updateList.size() == 200)
{
update updateList;
updateList.clear();
}
}
// outside the loop, need to see if there are any left-overs:
if(updateList.size() > 0)
{
update updateList;
}
Attribution to: Matt Lacey
This content is remixed from stackoverflow or stackexchange. Please visit https://salesforce.stackexchange.com/questions/3441