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
theAlchemist2889theAlchemist2889 

Need Help to Overcome Apex CPU time limit exceeded Error

I am working on a module which will de-duplicate contact records on insert/update but I am hitting into Apex CPU time limit exceeded error. I understand that to overcome it we need to optimize code a little but in the following code block there seems very little scope of optimizing it. Any help will be appreciated.

On Account we have a mulipicklist from where we can select the fields based on which the uniqueness of the contacts under this account will be defined. It can be different for difference account. The following code is a part of a handler class for trigger in which we have a map of old contact list with account Id as key (mapOfAccountIdWithItsContact) and a map with new contact list and account as key (newContactWithAccountMap) we iterate over these maps based on set of account whose contacts we have get in triiger. We have a map to stroe Lisst of fields to be used for contact uniqueness for each account (mapOfAccountWithFilters).

Here is the code snippet:

for(String accountId : accountIdSet){
            if(newContactWithAccountMap.get(accountId) != null){
                for(Contact newContact : newContactWithAccountMap.get(accountId)){
                    for(Contact oldContact : mapOfAccountIdWithItsContact.get(accountId)){
                        //Check for duplication only in the respective account, also this should not apply on insertion of Office contact
                        matchingContactFound = false;
                        if(oldContact.id != newContact.id){  //while insert, newContact's id will be null and while update it will verify that it is not matching itself with its old record. 
                            for(String filterFieldName : mapOfAccountWithFilters.get(accountId)){
                                if(oldContact.get(filterFieldName) == newContact.get(filterFieldName)){
                                    matchingContactFound = true;
                                    //If match is found update last de duplication date to today on old contact
                                    oldContact.Last_De_Duplication_Date__c = System.Today();
                                    oldContactsToUpdateSet.add(oldContact);
                                }else{
                                    matchingContactFound = false;
                                    break; //get another "old contact"
                                }
                            }
                        }
                        if(matchingContactFound){

                            //stop it from being inserted
                            duplicateContactSet.add(newContact.Id);
                            //newContact.addError('Contact cannot be inserted because a contact is already present based on the Master Target Identifier at client level.');
                            break; //get another "new contact"
                        }

                    }
                }
            }
        }



Any help in avoiding 4 loops or an alternate approach will be greatly appreciated. Thanks in advance.
Chinmay BhusariChinmay Bhusari
Hi ,
From the code it seems you are creating map for finding duplicate in the account .You don't need to do that as there is a relationship there . Check out this code.
trigger FindDupes on Lead (before insert, before update) {
  for (Lead myLead : Trigger.new) {
    if (myLead.Email != null) {
      List<Contact> dupes = [SELECT Id FROM Contact
                               WHERE Email = :myLead.Email];
      if (dupes.size() > 0) {
        String errorMessage = 'Duplicate contact found! '; 
        errorMessage += 'Record ID is ' + dupes[0].Id;
        myLead.addError(errorMessage);
      }
    }
  }
}

Hope this helps.
Regards.

AshwaniAshwani
@ Chinmay
Using SOQL in for loop is a bad practice and must not be used in anywhere in Salesforce. Here is link for best practice: https://developer.salesforce.com/page/Apex_Code_Best_Practices

@Shahid

First query and collect contact id and other matching fields as key. We generally say it composite keys.

Ex:

List<contac> conList = [SELECT AccountID, Id, Email From Contact Where AccountId in: accountSet];

MAp<String,Contact> contactMap = new Map<String,Contact>();

for(Contact con : conList)
{
    contactMap .put(con.accountID+con.ID+con.email, contact);
}

By this you can minimise the code.