-1

I worked on batch apex which will insert or update contact object from SIS_Staging__c object.

can anyone guide me how to handle error records here, from SIS_Staging__c object I am inserting or updating contact, if any record is failed then I want to update text field on SIS_Staging__c object with error message.

My apex class is below:

global class BatchSISstagingObject implements Database.Batchable<sObject>,  Database.stateful{
global Database.QueryLocator start(Database.BatchableContext BC) {
    return DataBase.getQueryLocator([SELECT Id,Name, First_Name__c,Last_Name__c,Email__c,Mailing_Country__c,SIS_Application_Id__c,AdmTyp__c,Resident_Tuition__c,ActnRsn__c,Admit_Term__c,Home_Country__c,Plan__c,Prog1__c,Prog__c,
                                      ProgActn__c
                                     FROM SIS_Staging__c WHERE Status__c = 'New'
                                    ]);
}
global void execute(Database.BatchableContext BC , List <SIS_Staging__c> staginglist) {
    Set<String> uniquekeySet = new Set<String>();
    for(SIS_Staging__c stagingObj : staginglist){
        uniquekeySet.add(stagingObj.Name);
    }
    List<Contact> contactToUpdate = new List<Contact>();
    List<Contact> contactToInsert = new List<Contact>();
    Map<String,Contact> studentIdTOContact = new Map<String,Contact>();
    List<Contact> conList2 = [SELECT ID,SIS_Student_ID__c,FirstName,LastName FROM CONTACT WHERE SIS_Student_ID__c IN:uniquekeySet];
    for(Contact conObj : conList2){
        studentIdTOContact.put(conObj.SIS_Student_ID__c,conObj);    
    }
    for (SIS_Staging__c acct : staginglist){ 
          if(studentIdTOContact.containsKey(acct.Name)){
             Contact con = studentIdTOContact.get(acct.Name);
             con.FirstName = acct.First_Name__c;
             con.LastName = acct.Last_Name__c;
             con.hed__AlternateEmail__c = acct.Email__c;
             con.SIS_Student_ID__c = acct.Name;
             con.hed__Country_of_Origin__c = acct.Home_Country__c;
             con.Current_Country_of_Study__c = acct.Mailing_Country__c;
             contactToUpdate.add(con);

          }else{
              Contact con = new Contact();
             con.FirstName = acct.First_Name__c;
             con.LastName = acct.Last_Name__c;
             con.hed__AlternateEmail__c = acct.Email__c;
             con.SIS_Student_ID__c = acct.Name;
             con.hed__Country_of_Origin__c = acct.Home_Country__c;
             con.Current_Country_of_Study__c = acct.Mailing_Country__c;
             contactToInsert.add(con);

          }
    }


    if(!contactToInsert.isEmpty()){
        insert contactToInsert;
    }
    if(!contactToUpdate.isEmpty()){

        Update contactToUpdate;
    }
0

You should use Databse.SaveResult for individually checking success/failure of each record update or insert.

if(!contactToUpdate.isEmpty()){ 
        Database.SaveResult[] updateResults = Database.update(contactToUpdate, false);

        List<SIS_Staging__c> errsStaging = new List<SIS_Staging__c>();
        for(Integer i=0;i<updateResults.size();i++){
            if (updateResults.get(i).isSuccess()){
                updateResults.get(i).getId();                    
            } else if (!updateResults.get(i).isSuccess()){
                errsStaging.add(new SIS_Staging__c(
                    Contact__c=contactToUpdate.get(i).Id, 
                    Error_Message__c=updateResults.get(i).getErrors().get(0).getMessage()
                ));
            }                
        }
        if(errsStaging.size()>0) insert errsCons;
    }
    if(!contactToInsert.isEmpty()){
        Database.SaveResult[] insertResults = Database.insert(contactToInsert, false);

        List<SIS_Staging__c> errsStaging = new List<SIS_Staging__c>();
        for(Integer i=0;i<insertResults.size();i++){
            if (insertResults.get(i).isSuccess()){ } 
            else if (!insertResults.get(i).isSuccess()){ // there is no contact as its not created
                errsStaging.add(new SIS_Staging__c(
                    Error_Message__c=insertResults.get(i).getErrors().get(0).getMessage()
                ));
            }                
        }
        if(errsStaging.size()>0) insert errsCons;
    }

However, note that in either updateResults or insertResults, you need to add more information in SIS_Staging__c like stack trace, fields etc apart from error message. You need multiple fields for logging all this info.

  • is it possible to update the error message on SIS_Staging__c record, I have Error__c field on SIS_Staging__c object, if any error occurs then I need to update that field with error message – Venkat Oct 21 at 9:59
  • modified answer for creating SIS_Staging__c – salesforce-sas Oct 21 at 10:03
  • your answer make sense for me but the thing is I don't have any relationship between Contact and SIS_Staging__c object, on both objects I have only SIS_Student_ID__c field which is same, basing on this field I am updating or inserting contact from SIS_Staging__c, is it possible for error message also to update SIS_Staging__c based on this SIS_Student_ID__c field – Venkat Oct 21 at 10:14
  • Yes, you can take this answer as reference and add logic in respective insert/update and success/failure blocks as required. If you have a different question, then I would suggest to open different question and close this question by clicking on tick. – salesforce-sas Oct 21 at 10:24
0

Use Database.insert which is partial insert the collection of data, please read Database.insert() Doc

List<Database.SaveResult> saveResultList = Database.insert(insertList, false);

// Iterate through saveResultList based on isSuccess capture the failed records
for (Database.SaveResult sr : saveResultList) {
    if (!sr.isSuccess()) {
        // Operation was successful, so get the ID of the record that was processed
        System.debug('Successfully inserted ' + sr.getId());
    }
    else {
        // Operation failed, so get all errors                
        for(Database.Error err : sr.getErrors()) {
            //store this info in new collection 
            System.debug(err.getStatusCode() + ': ' + err.getMessage());
            System.debug('feild Error ' + err.getFields());
        }
    }
}

For Update Case use Database.update(updateList,false) other will same

List<Database.SaveResult> saveResultList = Database.update(updateList, false);

    // Iterate through saveResultList based on isSuccess capture the failed records
    for (Database.SaveResult sr : saveResultList) {
        if (!sr.isSuccess()) {
            // Operation was successful, so get the ID of the record that was processed
            System.debug('Successfully inserted ' + sr.getId());
        }
        else {
            // Operation failed, so get all errors                
            for(Database.Error err : sr.getErrors()) {
                //store this info in new collection 
                System.debug(err.getStatusCode() + ': ' + err.getMessage());
                System.debug('feild Error ' + err.getFields());
            }
        }
    }

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.