0

I want to upsert a list of generic sobject with the external id field. This list of generic sobject contains records from different sobjects, where the sobject type will be unknown and will be determined only at run time.

I understand that I need to split this list into different list of specific sobject and then perform the upsert.

Just not sure how to create those different list of sobject from one list of generic sobject.

1 Answer 1

0

You could make use of the instanceof operator to determine the SObjectType. If you know which SObjectTypes to expect, you could do something like

List<Account> accounts = new List<Account>();
List<Opportunity> opportunities = new List<Opportunity>();
// ... and so on
for(SObject record : mySObjects) {
    if(record instanceof Account) {
        accounts.add((Account)record);
    } else if(record instanceof Opportunity) {
        opportunities.add((Opportunity)record);
    } // else if etc
}
upsert accounts MyExternalIdField__c;
upsert opportunities AlsoAnExternalIdField__c;
// etc

If you want a more generic approach, you could store everything in a Map<SObjectType, List> and then upsert from there:

Map<SObjectType, List<SObject>> recordsByType = new Map<SObjectType, List<SObject>>();
// populate map
for(SObject record : mySObjects) {
    SObjectType sObjectType = record.getSObjectType();
    if(!recordsByType.containsKey(sObjectType)) {
        recordsByType.put(sObjectType, new List<SObject>());
    } 
    recordsByType.get(sObjectType).add(record);
}

// loop through types and upsert
for(SObjectType sObjectType : recordsByType.keySet()) {
    List<SObject> records = recordsByType.get(sObjectType);
    SObjectField externalIdField = sObjectType.getDescribe().fields.getMap().get('My_External_Id__c');
    Database.upsert(records, externalIdField, true);
}

Note that for this to work the name of the external ID field needs to be exactly the same across all objects. If not, you have to implement additional logic to determine which field you want to use as external ID.

8
  • I forgot to mention, I want to keep the SObject types also dynamic. I can get the list of sobject types from a custom metadata or a custom label. Is it possible to initialize the list of sobject dynamically? May 21, 2021 at 15:06
  • Basically creating a list of sobject, given the api name of the sobject is retrieved from a custom label or custom metadata. May 21, 2021 at 15:32
  • SObject is a dynamic type, so you can just create a List<SObject>, and add new records created via sObject sObj = Schema.getGlobalDescribe().get(ObjectName).newSObject() ;
    – manjit5190
    May 21, 2021 at 16:18
  • 1
    You should simply have a Map<String, List<SObject>> where key is the object API name.
    – manjit5190
    May 21, 2021 at 16:29
  • 1
    @Steven.B This is perfect. sObjectType.getDescribe().fields.getMap().get('My_External_Id__c'); alongwith the map approach recommended by manjit5190 resolves my problem. May 21, 2021 at 17:20

You must log in to answer this question.

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