[SalesForce] Batch merging via Apex

Hello and thank you in advance. I'm looking to merge about 2000 records (about 1000 merges in total). My question is whether there is a best practices for this type of task. I'm able to merge 1 set of contacts via Execute Anonymous in the Developer Console:

Contact con = [select id,fax,phone from contact where id='xxxxx'];
Contact con2 = [select id,fax,phone from contact where id='xxxxx'];
database.merge(con, con2);

I would imagine I will need to employ a collection of tuples and do a foreach on them to handle the merging. Where do I start here, as far as storing a collection of tuples (e.g. {keeper1, mergee1},{keeper 2, mergee2})? Would I create a custom object that would house the tuples I intend to use for merging and then loop through them? When I have the Apex script written should I execute via the Execute Anonymous, or should I create a class to handle the work and invoke this a different way? Any help is greatly appreciated and sorry if my explanation is lacking.

Best Answer

Use a custom object so you can load them quickly. Use a class so you can process those all in one batch go. Because of DML limits, you won't be able to just execute anonymous, unless you feel like running your script hundreds of times.

For the custom object, use two lookup fields, the account to merge to, and the account to merge from. You could include a "status" field to indicate success/failure.

For your class, a simple batch class works:

public class BatchMerge implements Database.Batchable<Merge_Record__c> {
    public Database.QueryLocator start(Database.BatchableContext context) {
        return Database.getQueryLocator([SELECT Merge_To_Account__c, Merge_From_Account__c FROM Merge_Record__c]);
    }
    public void execute(Database.BatchableContext context, Merge_Record__c[] records) {
        for(Merge_Record__c record: records) {
            try {
                Database.merge(new Account(Id=record.Merge_To_Account__c), record.Merge_From_Account__c);
                record.Status__c = 'Success';
            } catch(exception e) {
                record.Status__c = 'Failed';
            }
        }
        update records;
    }
    public void finish(Database.BatchableContext context) {
    }
}

Make sure when you call your script, it uses a small enough scope size (not 200) to accommodate the massive number of DML statements you'll wrack up using this code:

Database.executeBatch(new BatchMerge(), 10);

Adjust this size to suit your needs.

Related Topic