0

I have a database with an object Voter_File_TX with over 15 million records and have over 700,000 contacts. I need to connect records that have the same First Name, Last Name, and Zipcode across these two via a look up field. 

I had to write a batch apex class that I execute anonymously beacuse of the enormous size of my database. I was told that the only way to do this is to do a batch class that will allow me to query more than 50,000 records at a time in order to match them up against each other. I was able to do this and have them connected in my sandbox where I do not have 15 million records.

However when I ran this into my production enviroment it failed because of SF limit of of 10,000 DML, or ability to change records, at a time. I was then also told that I need to write a batch class within this batch class in order to get over this limit as well. 

Can you please help me out with this I am stuck with this part. 

Below is the Apex Batch Class code. 

    global class UpdateVoterFileonContacts implements Database.Batchable<sObject>{
    global Database.QueryLocator start(Database.BatchableContext BC){
        String query = ' Select ID,First_Name__c, Last_Name__c,Zipcode__c from Voter_File_TX__c';
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext info, List<Voter_File_TX__c> scope){
        Set<String> set_Str = new Set<string>();
        Map<String,Contact> mp_Cont;

        for(Contact Cont : [Select ID,FirstName,LastName,MailingPostalCode, Voter_File_ID__c From Contact where Contact.voter_File_ID__c = null AND Contact.RNC_ID__c != null LIMIT 50000] ){
            if(mp_Cont==null){
                mp_Cont = new Map<String,Contact>();
            }
            mp_Cont.put(Cont.FirstName +''+ Cont.LastName +''+Cont.MailingPostalCode,Cont);
        }
        for(Voter_File_TX__c VoterList : scope){
            if(mp_Cont!=null && mp_Cont.containsKey(VoterList.First_Name__c +''+ VoterList.Last_Name__c+''+ VoterList.Zipcode__c))

            {
                mp_Cont.get(VoterList.First_Name__c +''+ VoterList.Last_Name__c +''+ VoterList.Zipcode__c).Voter_File_ID__c = VoterList.id;
            }
        }
        /* if(mp_Cont!=null && mp_Cont.values()!=null){
            update mp_Cont.values();
        }
        */

        if(!mp_Cont.isEmpty()){
            update mp_Cont.values();
        }
    }

    global void finish(Database.BatchableContext info){

    }
}

I was told that I need to add this type of call to my apex code but I am not sure where how this would transalte into my apex batch class code because I am already currently writting an apex batch class and because i do not know where exactly to add it. 

Example Code to add: 

 List abc = [Select Id from Contact where Amount =100]; 
for(i=0; i<=abc.size(); i++) 
{ 
List a = abc[i]; 
a.add(abc); 
}

Can anyone please help implment this or tell me of another way wherre I can get around Salesforce govern limit of only updating 10,000 records at a time?

Thanks!

0
1

Unless I am missing something I would come at it from the Contact Object and reduction it to this:

Note Add a formula field, in this case ConcatField__c on the Voter object to create the key of the first, last, and zip so it can be used in the query

global class UpdateVoterFileonContacts implements Database.Batchable<sObject>{
    global Database.QueryLocator start(Database.BatchableContext BC){
        return Database.getQueryLocator([Select ID,FirstName,LastName,MailingPostalCode, Voter_File_ID__c From Contact where Contact.voter_File_ID__c = null AND Contact.RNC_ID__c != null]);
    }

    global void execute(Database.BatchableContext info, List<Contact> scope){
        Map<String,Voter_File_TX__c> mp_Voter;

        for(Contact c : (Contact[])scope){
            mp_Voter.put(getKey(c), New Voter_File_TX__c());
        }

        for(Voter_File_TX__c v : [Select ConcatField__c, ID,First_Name__c, Last_Name__c,Zipcode__c from Voter_File_TX__c Where ConcatField__c In :mp_Voter.keySet()]){
            mp_Voter.put(v.ConcatField__c,v);
        }

        for(Contact Cont : (Contact[])scope){
            Voter_File_TX__c tmp = mp_Voter.get(getKey(Cont));
            Cont.Voter_File_ID__c = tmp.Id;
        }

        update scope;
    }

    global void finish(Database.BatchableContext info){

    }

    private string getKey(Contact c){
        return c == null ? null : (c.FirstName + c.LastName + c.MailingPostalCode);
    }
}

Essentially, the start query gets contacts that match the criteria. Then in the execute we populate a collection with the values from the contact to create the concat key. After that we query for the Voter records and place them in the map.

Then we iterate over the scope again to set the Id field to either null if it was not found or the Id of the voter record.

3
  • Thanks for your help, but this code is not working because I do not need the extra ContactFeild__c. Just to give you a basic rundown: I am trying to connect to records across two objects, 1. Contacts and 2. Voter_File_TX__c, via a lookup field that exists Voter_File_TX__c custom object of Voter_File_TX__c.Contact__c. Records across these two objects should be connected on a one to one basis if they have matching First Name, Last Name, and Zipcodes. – Morning Man Apr 21 '17 at 19:27
  • Well good luck then. This is the easiest and simplest way to do it imho with the additional field. Otherwise you are going to continue to run into issues trying to find the matching records – Eric Apr 21 '17 at 19:30
  • And it's not a contact field it is a concat field holding the combo of the fields that make up the search criteria – Eric Apr 21 '17 at 19:35

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.