function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Dominik PatakyDominik Pataky 

Transaction seems to fail when mixing inserts and updates

Hello everyone,
after I posted this wrongly on https://success.salesforce.com/answers?id=9063A000000p6oO I now repost it here and still seek advice!

We are trying to sync some JSON objects (that came from a parser) with our database. There's a list of these objects that is iterated over which has an identifier that is mapped with Customer_Rating objects (via two other objects) from another list. That way, the sync should distinguish between "update an existing object in the database with new values" or "create a new database object with all values".

Firstly we collect all existing Customer_Ratings:
List<Customer_Rating__c> existingRatingList = new List<Customer_Rating__c>(); 
existingRatingList = [SELECT Creation_Date__c, Reply__c, Opportunity__c FROM Customer_Rating__c];
The following list is used to create a new mapping between Opportunity identifiers with the objects above:
Map<String, Customer_Rating__c> existingRatingOppMap = new Map<String, Customer_Rating__c>(); 
for (Customer_Rating__c rating : existingRatingList) { 
    existingRatingOppMap.put(rating.Opportunity__c, rating); 
}
And finally, there's another mapping from Invoice_Number to Opportunities:
Map<Id, Invoice__c> invoiceMap = new Map<Id, Invoice__c>([SELECT id, name, Invoice_Number__c, Opportunity__c FROM Invoice__c]); 
Map<String, String> invoiceOppMap = new Map<String, String>(); 
for (Invoice__c invoice : invoiceMap.values()) { 
    invoiceOppMap.put(invoice.Invoice_Number__c, invoice.Opportunity__c); 
}
Using these three code blocks, we have a link between the Invoice_Number and a possibly existing rating.

Now we iterate over a list of objects that create a link to Invoices via the Invoice_Number and in this block the code should make the difference mentioned above:
if (invoiceOppMap.keySet().contains(invoice_num)) {
    String oppId = invoiceOppMap.get(invoice_num);
    Customer_Rating__c rating;
               
    if (existingRatingOppMap.keySet().contains(oppId)) {
         // Case: an Opportunity with rating with this order_id already exists, so an update is needed.
         rating = existingRatingOppMap.remove(oppId);
         rating.Creation_Date__c = feedback.getSubmitted();      
         update rating;
     } else {
         // Case: no Opportunity (via the invoice referenced by the order_id)
         // with an existing rating was found, a new one is created.
         rating = new Customer_Rating__c();
         rating.Comment__c = feedback.review;
         rating.Opportunity__c = oppId;
         rating.Rating__c = feedback.rating;
         rating.Creation_Date__c = feedback.getSubmitted();
                    
         insert rating;
     }
}
Now the blocker we tried to solve: when running this whole function via the Apex anonymous execution window it starts, holds at "Unpacking results" and does not finish. The log shows, that both - inserts and updates - were done, but they are not commited to the database.
If we then remove the update path and run only the inserts it works as expected.
We also looked at the activated triggers, but they are all activated in the insert path. Update does not fire any triggers.

Any ideas? Any race conditions we overlooked? 
Tips to create better queries are also very welcome!
Virendra Singh NarukaVirendra Singh Naruka
Hi Dominik,

Try bulk   Insert and bulk Updates  instead of Single insert and Single Updates.
Dominik PatakyDominik Pataky
Hi Virendra,thanks for your reply.
As mentioned in https://developer.salesforce.com/forums/#!/feedtype=SINGLE_QUESTION_DETAIL&dc=Developer_Forums&criteria=ALLQUESTIONS&id=9060G000000XdyGQAS I switched back to bulk inserts/updates, but that did not solve the problem.