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.