+ Start a Discussion
Kenji775Kenji775 

Upsert List not sure if I'm doing this right

Hey Guys,

I've just been having terrible luck recently. Everything I do seems to casue an internal salesforce error. What I am working on at this point is upserting a list of person accounts based on an external id field (SSN__C). I've never done an upsert before (I know, I'm lame) so I am unsure if the error I am getting is due to me getting the process wrong, or if I found yet another bug. The list of accounts comes from parsing a CSV file, and if I change the upsert to just an insert, it works fine so I know the data it's trying to pass in for creating is legit. Here is the relevant code.

//get a list of people to upsert by parsing the CSV file into a list of account objects.
 list<Account> accounts = csvTosObject(parseResult, 'Account');
 

 system.debug('========================= List of Accounts');
 system.debug(accounts); //shows all accounts parsed fine
                         
//upsert them (need to get a reference to the external field to use for id)
Schema.SObjectField f = Account.Fields.SSN__c;                        
List<Database.upsertResult> accountSaveResult = Database.upsert(accounts,f); // <---- Explodes

//if instead of an upsert I have an insert, it works fine. So i know the data is good.
//List<Database.saveResult> accountSaveResult = Database.Insert(accounts,false);

//iterate the person save results to create the import result log
for(database.UpsertResult r : accountSaveResult)
{
    if(r.isSuccess())
    {
        if(r.isCreated())
        {
            personCreates++;
        }
        else
        {
            personUpdates++;
        }
    }
    else
    {
       personErrors++;
        for(Database.Error e : r.getErrors())
        {
            personErrorText.add(e.getMessage());
        }
    }
}

 
Otherwise I can break the operation into two separate insert and update statments probably (seems hackish but it would work) but I'd prefer to just upsert if I can. Any help is appreciated. Thanks!

 

Kenji775Kenji775

If I can't get upsert working, I wrote this alternate way, but it seems pretty clunky. If anyone has a more efficient way I'd love to hear it.

 //******* BEGIN GHETTO UPSERT PROCESS *******//
 set<string> ssnList = new set<string>();
 map<String,Account> ssnToId = new map<String,Account>();
 list<Account> updateAccounts = new list<Account>();
 list<Account> insertAccounts = new list<Account>();
 for(Account a : accounts)
 {
     ssnList.add(a.SSN__c);
 }
 list<Account> existingAccounts = [select id, SSN__c from account where SSN__c in :ssnList]; 
 for(Account ex : existingAccounts)
 { 
     ssnToId.put(ex.SSN__c,ex);
 }
 for(Account a : accounts)
 {
     Account thisAccount;
     if(ssnToId.containsKey(a.SSN__c))
     {
         thisAccount = a.clone(true,false);
         thisAccount = ssnToId.get(a.SSN__c);
         updateAccounts.add(thisAccount);
     }
     else
     {
         thisAccount = a;
         insertAccounts.add(thisAccount);
     }
 }
 system.debug('============= UPDATE ACCOUNTS');
 system.debug(updateAccounts);
 
 system.debug('============= INSERT ACCOUNTS');
 system.debug(insertAccounts);
                          
 List<Database.saveResult> accountUpdateResult = Database.update(updateAccounts,false);
 for(database.saveResult r : accountUpdateResult)
 {
    if(r.isSuccess())
    {
        personUpdates++;
    }
    else
    {
       personErrors++;
        for(Database.Error e : r.getErrors())
        {
            personErrorText.add(e.getMessage());
        }
    }
 }
 List<Database.saveResult> accountInsertResult = Database.Insert(insertAccounts,false);
 for(database.saveResult r : accountInsertResult)
 {
    if(r.isSuccess())
    {
        personCreates++;
    }
    else
    {
       personErrors++;
        for(Database.Error e : r.getErrors())
        {
            personErrorText.add(e.getMessage());
        }
    }
 }                         
 
 //******* END DIRTY HACK UPSERT CODE *******************//

 

 

SuperfellSuperfell

Can you post the exact error you get.

Kenji775Kenji775

It's just

'Internal System Error'.

 

This is for an email service that parses an attached CSV file, so that is all the details the debug log would give me. I don't have a great way to test it with execute anon and get more details. But it's just the standard platform error it seems. I'll see if I can dig up anything else. 

Kenji775Kenji775

The exact text from the stack trace is

12:21:11.153 (153644000)|SYSTEM_METHOD_ENTRY|[133]|Database.upsert(LIST<SObject>, Schema.SObjectField)
12:21:11.154 (154003000)|SYSTEM_METHOD_EXIT|[133]|Database.upsert(LIST<SObject>, Schema.SObjectField)
12:21:11.156 (156058000)|FATAL_ERROR|Internal Salesforce.com Error

 Line 133 is the upsert line.

132: Schema.SObjectField f = Account.Fields.SSN__c;
133: List<Database.upsertResult> accountSaveResult = Database.upsert(accounts,f);

 



You can see the full trace at

http://pastebin.com/raw.php?i=iVWcxgys 

SuperfellSuperfell

There should be a long number that goes with it.

Kenji775Kenji775
I know there normally is, but it doesn't seem like it for this error. I'll keep trying to see if I can get it to spit one out.
rungerrunger

You can't use List<sobject> with upsert.  The parameterized type of the list must be a concrete entity type.