3

Hello Salesforce community,

I have a problem with Callouts and Commits in APEX: Error is: "You have uncommitted work pending."

Fact in Salesforce:

  • You can't do a callout when you have outstanding (uncommited) DML statements

My process:

For a number of SObjects X__c I need to do the following:

  • Do a callout to a webservice to get data which builds the X__c record
  • Create an Account and fill the ForeignKey in X__c with the ID of the created Account.

But the Account.id is only available AFTER the insert. And I can't do the insert because the loop has other callouts to do.

Possible solution:

  • Generate all the X__c objects with all their Callouts
  • Store result in a List of X__c objects
  • Put all created Accounts also in a List
  • Somehow 'connect' each Account to its matching X__c (in a third List?)
  • Upsert both lists at the end.

This seems to me like a difficult solution just because Salesforce doesn't allow callouts between DML statements.

Is there another, better, way to program this?

Thanks in advance for your help.

3

Lists are ordered, so you can just insert your accounts first:

CalloutResult[] results = doCallouts();
Account[] accounts = new Account[0];
for(CalloutResult result: results) {
    accounts.add(new Account( ... ));
}
insert accounts;
X__c[] xrecords = new X__c[0];
for(CalloutResult result: results) {
    // Use the first account in the list, remove it from memory
    xrecords.add(new X__c( ..., Account__c = accounts.remove(0).Id));
}
insert xrecords;
  • Thanks @sfdcfox, The final solution was based on this one. First I did all the callouts and put them in a Map. Then a loop through the Map and based on the Key I Upserted the records in Account and X__c. – BertC Jun 28 '16 at 6:41
0
  1. Create savepoint:

    Savepoint sp = Database.setSavepoint();

  2. Create temporaly account and X__c record, connect them

  3. Do all callouts in future, update your records accordingly

  4. In case if any callout fail, do restore within:

    Database.rollback(sp);

Thats should work if you using your 3rd party to pull data, if you create something. You have to build technique, where SF and 3rd party should commit its operations etc.

0

If the option of going with Lists works for you, then go with that. It will be simpler.


I've had success in the past by creating unique keys for all the records involved. If you are lucky you might have a external Id on the Account objects that can fulfill that role. Failing that, any other field or collection of fields that is unique to each Account before it is inserted.

Then you maintain a map from the unique key to each Account that is going to be inserted after all the callouts are complete.

After bulk inserting the Accounts you can then revisit each X__c and find the corresponding Account by the unique key and get the new Account Id. Then upsert all the X__c records.

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.