[SalesForce] Is it possible to Upsert a List with external ID specified

I'm getting an error when attempting to compile my Apex:

Upsert requires a concrete SObject type

In my code, I'm unable to create a concrete declaration for the container which I want to upsert. Any help would be appreciated.

    String type = 'Account';  
    System.Type typeOfMappedSObject = System.Type.forName(type);
    String qry = 'Select id from ' + typeOfMappedSObject.getName() + ' Where name=null'; 
    List<SObject> s_targetRecordList = Database.query(qry); 

    //...

    Map<String,Schema.SObjectField> sObjFieldMap =  sobjDscrbResult.fields.getMap(); 

… at this point I call createSObject(type) and receive a new SObject with specified type passed in as a string and assign it to a generic SObject which I later add to s_targetRecordList as seen below.

    SObject s_targetSObject = createSObject(type); 

    //... 

    for(String fieldName : sObjFieldMap.keyset()){
        if(fieldName == sfsmRecord.TargetFieldName__c){
            s_externalIdField = sObjFieldMap.get(fieldName);
        }
     }

    //... 

    s_targetRecordList.add(s_targetSObject);

    //.... 

    List<Database.UpsertResult> upsrtResultList = Database.upsert(s_targetRecordList, s_externalIdField, false);

One final note, if I remove the externalIDField from the Upsert call then I don't get the above error…

Best Answer

That is correct, you cannot upsert on a List of SObject when you specify external ID. Error: "Upsert with a field specification requires a concrete SObject type"

Please vote for the idea here : https://success.salesforce.com/ideaView?id=08730000000aNhVAAU

Conceptually what you require is : DYNAMIC TYPECASTING. But I am not sure if dynamic typecasting can be done.

Currently this should work for you:

String type = 'Account'; 
System.Type typeOfMappedSObject = System.Type.forName(type);
String qry = 'Select id from ' + typeOfMappedSObject.getName() + ' Where name=null'; 
List<SObject> s_targetRecordList = Database.query(qry); 
if(!s_targetRecordList.IsEmpty() && type == 'Account'){
    List<Account> accList = new List<Account>();
    accList = (List<Account>)s_targetRecordList;
}

Keep using accList for further operation including upsert.

Related Topic