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
Kumaresan M 2Kumaresan M 2 

Record locking in detail record when i try to insert details in future method ?

I am getting error "UNABLE_TO_LOCK_ROW, unable to obtain exclusive access to this record: []" when i try to insert detail record.
Eligible Employee is detail object, Master is inserted already.
Here is my code, where i am looping string list and calling future methods to process more records asynchrously: 
                    set<string> str=new  set<string>();  
                    List<string> strLst=new  List<string>();            
                    Integer w=0;
                    for(string l:LoadedMSIDList){
                        ResultString=ResultString+l+',';
                        Eligible_Employees__c e=new Eligible_Employees__c();
                        if(EmployeeMap.containskey(l)){                  
                                str.add(l);
                                strLst.add(l);
                                ResultString=ResultString+'Successfully inserted into system \n';
                        }
                        else{
                            ResultString=ResultString+'Invalid MSID \n';
                        }
                        w++;
                        if(strLst.size()>1999 || w==LoadedMSIDList.size()){
                            DMLbatch(str,strLst,EligibilityRecord.id);
                            str.clear();
                            strLst.clear();
                        }
                                                         
                    }


Here is my future method which will insert detail records asynchronuosly:

@future(callout=false)
    public static void DMLbatch(Set<string> str,List<String> strLst,string myId){
        List<Eligible_Employees__c> EligibleEmployeeList1=new List<Eligible_Employees__c>();
        Map<string,Employee__c> EmployeeMaps=new Map<string,Employee__c>();
        List<Employee__c> EmpLst=WaiversUtility.getEmployeeListonMSID(str);       
        for(Employee__c emp:EmpLst){
            EmployeeMaps.put(emp.Emp_ID__c,emp);                       
        }      
        for(string s:strLst){    
            Eligible_Employees__c e1=new Eligible_Employees__c();
            e1.Employee__c=EmployeeMaps.get(s).id;
            e1.Eligibility__c=myId;
            EligibleEmployeeList1.add(e1);
        } 
        insert EligibleEmployeeList1;
    }

Please help me on this to resolve this.
bob_buzzardbob_buzzard
I reckon this is because you are executing your @future jobs from within a loop and they are conflicting with each other.  This is particularly likely if there is no order to the child records being inserted (e.g. each @future job is inserting child records to the same set of parent objects).   The following articles have more information:

https://developer.salesforce.com/page/The_Salesforce_Bulk_API_-_Maximizing_Parallelism_and_Throughput_Performance_When_Integrating_or_Loading_Large_Data_Volumes

https://developer.salesforce.com/blogs/engineering/2014/08/managing-task-locks-data-loads.html
Kumaresan M 2Kumaresan M 2
Thanks for your reply. How do i implement bulk API through Apex, I didnt find any example of how to write bulk api in salesforce ?
Do you have any thing for this ?
bob_buzzardbob_buzzard
You don't have a bulk API in Apex - you'd typically use something like batch Apex instead.
Kumaresan M 2Kumaresan M 2
Yeah. We implemented batch apex to process this. Even though if you use batch to process our csv file which has around 5MB, we are getting heap size error while executing (We are using iterator to process CSV file in start method) at the first batch itself in start method itself.. Is there any way to avoid this ?

Iterator Class:
global with sharing class CSVIterator implements Iterator<String>, Iterable<String>
{
   private String m_CSVData;
   private String m_introValue;
   public CSVIterator(String fileData, String introValue)
   {
      m_CSVData = fileData;
      m_introValue = introValue;
   }
   global Boolean hasNext()
   {
      return m_CSVData.length() > 1 ? true : false;
   }
   global String next()
   {
      String row = m_CSVData.subString(0, m_CSVData.indexOf(m_introValue));
      m_CSVData = m_CSVData.subString(m_CSVData.indexOf(m_introValue) + m_introValue.length(),m_CSVData.length());
      return row;
   }
   global Iterator<String> Iterator()
   {
      return this;  
   }
}

Batch Class:

global class ReadAndPopulateBatch implements Database.batchable<String>, Database.Stateful
{
   public String m_csvFile;
   public String fileId;
   public Map<Integer,string>  OrderMap;
  
   global Iterable<String> start(Database.batchableContext batchableContext)
   {
       return new CSVIterator(m_csvFile,'\n');
   }
   global void execute(Database.BatchableContext batchableContext, List<String> scope) 
   {
       system.debug('************Limits.getHeapSize()'+Limits.getHeapSize());
       list<Wav_Custom_data__c> insertlist=new list<Wav_Custom_data__c>();
      .... code to process reocrds to insert....
       Database.Insert(insertlist);
       insertlist.clear();
       system.debug('************Limits.getHeapSize()2'+Limits.getHeapSize());
   }
   global void finish(Database.BatchableContext batchableContext){
  
   }
}