5

For one of the requirements I have to write code to update multiple records of different objects. Originally I was planning to do the obvious: get needed records, change some value, update these lists, but then I though... Why don't I just use a list of generic SObject?

Then I tried to find some pros and cons of using List<SObject> vs. multiple lists per object type and I could only find one:

  • Only 1 update needed for all records(= less DML operations)

Example code:

List<Opportunity> opps = [SELECT Id, OwnerId, Name FROM Opportunity WHERE Name LIKE :nameString AND OwnerId IN :fromUsers];
List<Lead> leads = [SELECT Id, OwnerId, Name FROM Lead WHERE Name LIKE :nameString AND OwnerId IN :fromUsers];
List<SomeCustomObject__c> objs = [SELECT Id, OwnerId, Name FROM SomeCustomObject__c WHERE Name LIKE :nameString AND OwnerId IN :fromUsers];
// do something with these lists, based on the requirements
update opps;
update leads;
update objs;

But this will require 3 DML operations(+any other triggered by triggers/processes/workflows). But we could simply replace the 3 DML operations by the following:

List<SObject> allRecordsToUpdate = new List<SObject>();
allRecordsToUpdate.addAll((List<SObject>)opps);
allRecordsToUpdate.addAll((List<SObject>)leads);
allRecordsToUpdate.addAll((List<SObject>)objs);
update allRecordsToUpdate;

I know, that in this case we only save 2 DML operations, but once we will need to update 10, 20, 30, whatever... different objects it might be a lifesaver.

So the question is: what are the pros and cons of using List<SObject>?

6

For cons, using SObject instead a concrete type restricts the usage of upsert by external ID, and you can't upsert generic SObject lists (the variable may be SObject[], but the actual list in memory must be a concrete type), and reduces the maximum number of records per operation to 2,000 by a feature known as chunking.

For pros, it reduces CPU usage slightly and reduces DML operations that count towards the limit (but not the row counts). Keep in mind, though, that this method is also limited to 10 "chunks" of data when you mix types.

A chunk is a consecutive run of up to 200 records of the same type. So, if you had 201 opportunities, 50 accounts, and 425 contacts, that would be a total of 6 chunks of the allowed 10, assuming all of the records were next to each other.

In practice, this is rarely a problem, but you might run into this issue if you've got alternating records, such as Account, Contact, Opportunity, Account, Contact, Opportunity...

For upsert, the following is allowed:

SObject[] a = [SELECT Id FROM Account];

But the following is not:

SObject[] a = new SObject[0];
a.addAll([SELECT Id FROM Account]);

When doing upsert on a list, each set of inserts or updates, in groups of 200, count as a chunk. The 10 chunk limit applies here as well.

  • So if I understand correctly, if I have 9 different types with 200 records each and another type with 201 record using SObject list to update is not an option anymore? – Novarg May 19 '17 at 12:27
  • @Novarg Yes, when mixing types, 10 is the limit. However, that still gives you the capacity to pack up to 1,500 DML operations into the 150 DML operation limit, which isn't a bad trade off. – sfdcfox May 19 '17 at 12:32
  • @Novarg For example, one novel use case is that I'll set up 10 different objects in a unit test, insert them all at once, then update any parent record fields, and do an update, saving me up 18 DML operations in my unit test context. It's kind of rare to be able to take advantage of this in production code, but when you can, you may as well use it. – sfdcfox May 19 '17 at 12:35

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.