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
Josh Davis 47Josh Davis 47 

Duplicate Rule Errors causing class to fail to commit - how to get around?

Hey Everyone, I am having some issues with a Duplicate Rule and some APEX code.  The code itself works fine and I have no problems with its function, other than how it relates to the standard Duplicate Rules in Salesforce.

(illustration below) Through the Data Loader, I am inserting 227 Contacts with a batch size of 200, this splits into two batches, the 1st batch has a single record which matches according to the duplicate rule and so is prevented from being inserted resulting in a batch size of 199, the second batch has 27 contacts.  A trigger then passes Trigger.new into my AsyncProcessing class, which its only function is to take the batches of contacts, extract their IDs and comma seperate join them in groups of 100 and create a record on a custom object called 'AsyncRequests__c'.  

Everything functions correctly, if I System.Debug() the array sizes before and after insert, I show 2 AsyncRequest records for the first batch of 199 and 1 AsyncRequest record for the second batch of 27.  This is where things go sideways.  Even though there are no errors shown anywhere in the code (see the debug log below), the AsyncRequest__c records are not committed for the batch that has a duplicate error in it.  The contacts are successfully inserted (199) but my trigger/class that creates the AsyncRecords__c are not.  

My question is, how can I get around this or trap the error that is causing the roll back?  I am not sure why it successfully inserts the 199 contacts, my code takes those 199 then successfully inserts 2 AsyncRequest__c records, then ultimately rolls back the insert of the AsyncRequest__c records.  Since the record that was in error was never inserted why does it only affect my code of creating the custom records but the contacts themselves are inserted successfully?  Any direction would be great.  Thanks in Advance.
User-added image
Contact Trigger
trigger AsyncNPICall on Contact (after insert, after update) {
    System.debug(trigger.new);
    AsyncProcessing.handleNPITrigger(trigger.new, trigger.newMap,
        trigger.oldMap, trigger.operationType);
}

Class
public class AsyncProcessing {

	// Simple protection from workflows and triggers
	private static Boolean alreadyProcessed = false;	
	

	public static void handleNPITrigger(List<Contact> ContactList, 
		Map<ID, Contact> newMap, Map<ID, Contact> oldMap, 
		 TriggerOperation operation)
	{
		if(alreadyProcessed) return;
		alreadyProcessed = true;


		List<AsyncRequest__c> newAsyncRequests = new List<AsyncRequest__c>();
		List<String> textChangedIds = new List<ID>();

		System.debug('Total Contacts in Contact List: ' + ContactList.size());
		for(Contact co: ContactList)
		{
			if(operation == TriggerOperation.AFTER_INSERT && !String.isBlank(co.NPI__c) || co.NPI__c!= oldMap.get(co.id).NPI__c && !String.isBlank(co.NPI__c)) {
				textChangedIds.add(co.id); 
			}
			
			if(textChangedIds.size()>99) {
				newAsyncRequests.add(
					new AsyncRequest__c(
						AsyncType__c = 'NPI API Call',
						Params2__c = string.Join(textChangedIds,',')
					)
				);
				System.debug('Current Async Request Size in Loop: '+newAsyncRequests.size());
				textChangedIds.clear();
			}
		}

		if(textChangedIds.size()>0){
			newAsyncRequests.add(
				new AsyncRequest__c(
					AsyncType__c = 'NPI API Call',
					Params2__c = string.Join(textChangedIds,',')
				)
			);
		}
		System.debug('Async Request Size:' + newAsyncRequests.size());
		for( AsyncRequest__c a: newAsyncRequests){
			System.debug(a.Name + a.params2__c);
		}

		Database.SaveResult[] srList = database.insert(newAsyncRequests,false);
		system.debug(srList+'srList+++');
		for (Database.SaveResult sr : srList) {
		if (sr.isSuccess()) {
			// Operation was successful, so get the ID of the record that was processed
			System.debug('Successfully inserted AsyncRequest__c. AsyncRequest__c ID: ' + sr.getId());
		}else {
			for(Database.Error err : sr.getErrors()) {
				System.debug('The following error has occurred.');                    
				System.debug(err.getStatusCode() + ': ' + err.getMessage());
				System.debug('Error Ids: ' + err.getFields());
        	}
		}
		}


		for (AsyncRequest__c ar : newAsyncRequests) {
			System.debug(ar.id);
		}
	}

}

User-added image
VinayVinay (Salesforce Developers) 
Hi Josh,

Check below link which can help you.

https://salesforce.stackexchange.com/questions/78670/disable-duplicate-check-for-apex-class

Thanks,
Josh Davis 47Josh Davis 47
Hey Vinay! Thanks for the response, if I understand it correctly, that is essentially bypassing any duplicate rules for the code that is written?  I am trying to understand how Salesforce intended this to work together, because Duplicate rules are a very important and powerful part of the platform I would rather work along side them and not just bypass them.  I am not understanding why it affects my code in this situtation, the correct number of contacts get inserted in the first batch (199 because 1 failed due to duplcate rules), then my code processes the 199 successful contacts and it still causes my code to revert, even though my code does nothing other than create some additional records from the successful 199.  Maybe there is a fundamental piece of how this code operates that I am missing but it seems there should be a way for these two to co-exist.