5

I am having trouble in upserting a List. sObject may be Task or Account

public static void onTaskStatusChange(List<Task> newList, Map<Id, Task> oldMap) {
        List<SObject> objectUpsertList = new List<SObject>();

        for(Task newTask : newList) {
            Task oldTask = null;

            if(oldMap != null && oldMap.get(newTask.Id) != null) {
                oldTask = oldMap.get(newTask.Id);
            }

            objectUpsertList = HelperClass.maintainTasks(newTask, oldTask);

            if(objectUpsertList.isEmpty()) {
                continue;
            }
        }

        if(!objectUpsertList.isEmpty()) {
            upsert objectUpsertList;
        }
    }

I am having error, while wriitting Test Method for this.

System.DmlException: Update failed. First exception on row 0 with id 00Tc000000CIr9iEAD; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, Task_AfterUpdate: execution of AfterUpdate

caused by: System.TypeException: DML on generic List only allowed for insert, update or delete

Is there any work around for this?

5

Use strictly insert or update. It's easy to found out which you should do since if there is an Id on the record it will always be update and the other way around for insert. You can even use 2 separate lists for this. 1 for update and 1 for insert. Just do a check for them.

List<SObject> updObjs = new List<SObject>();
List<SObject> insObjs = new List<SOBject>();
for (.... ...: ....)
{
  if (something.Id != null)
    updObjs.add(something);
  else
    insObjs.add(something);
}
insert insObjs;
update updObjs;
1
 sObject sObj = Schema.getGlobalDescribe().get('Account').newSObject();

 sObj.put('name' , 'test');

 Account ResultFinal=(Account )sObj;

 upsert ResultFinal opt_external_id;
  • can you add more details to your answer rather than just the code to help how it addresses the question – Vamsi Krishna Mar 25 '15 at 23:44
0

Have you tried:

database.upsert(objectUpsertList, Id, true);

https://www.salesforce.com/us/developer/docs/apexcode/Content/apex_methods_system_database.htm#apex_System_Database_upsert

  • Upsert DML operation, is eligible only for a single record SObject. It won't work in this case. Cheers! – Endrit Sino May 22 '15 at 12:26
  • Not true, from the documentation: public static Database.UpsertResult[] upsert(sObject[] recordsToUpsert, Schema.SObjectField externalIdField, Boolean allOrNone) – Davin Casey May 25 '15 at 9:25
  • Actually, strange as it may sound, I have tried it, and it fails to upsert a collection of SObjects through this approach. For a quick test, please refer, to my test snippet: gist.github.com/EndritSino/710ef9cb4e8fdc43b148 . Thank you! – Endrit Sino May 25 '15 at 10:33
0

I'm running on the same problem. And basically for this problem there are two approaces:

  1. Either you, save two(or more) collections of the target objets to upsert, and go through the SObject List, and typecast the items individually and save them to the collections.(N UPSERT statements & N Collections for N type of Objects)

  2. Or, you filter the SObjects, by detecting in Database, if they exist or not. Divide only in two different lists: soUpdateList & soInsertList. (2 DML Operations, 1 SOQL query for ever N Objects, but you can see the efficency in the memory, here.)

Here is a workaround for the second approach: http://www.sundoginteractive.com/sunblog/posts/upserts-with-generic-sobjects-salesforce

Hope it helps! E.

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.