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
jcasazzajcasazza 

addError() in bulk triggers

Hello, 

 

I am trying to prevent a duplicate record from being inserted so I am using the sObject.addError() method in a before insert trigger. The trigger was written to handle bulk operations. In my test class When I insert a duplicate record, I catch the exception from the addError() call. When I run a bulk test,  the behavior is not what I expected.

 

This is an example, not the actual code:

Case newCase = new case(Subject = 'Subject1', SuppliedEmail='test@test.com'; Origin="Email to Case'));

insert new Case;

 

List<Case> caseList = new List<Case>();

caseList.add(new case(Subject = 'Subject1', SuppliedEmail='test@test.com'; Origin="Email to Case'));

caseList.add(new case(.Subject = 'Subject2', SuppliedEmail='testx@test.com'; Origin="Email to Case'));

caseList.add(new case(Subject = 'Subject3', SuppliedEmail='testy@test.com'; Origin="Email to Case'));

caseList.add(new case(Subject = 'Subject4', SuppliedEmail='testz@test.com'; Origin="Email to Case'));

insert caseList;

 

When the insert caseList is executed, I am expecting the first record to fail due to the addError call that will be executed because it is a duplicate of the case created in the first insert operation. But I am also expecting the other three cases to be created.

 

When I query the Case object for the other 3 cases, my assertion fails because I am expecting 1 record to exist for 'Subject2' but the actual is 0.

 

I didn't think addError caused a rollback on all records in a bulk transaction. Am I missing something?

 

Thanks in advance,

 

Jim

Ankit AroraAnkit Arora

addError() doesn't roll back your insertion but it prevent the further execution of the script, so you data is never inserted if an you throw an error on UI.

 

I would suggest you to first take all values in any map and check with database for duplicate values. If there are duplicate values then create another list and insert the rest others. Now using that list throw an error listing all names of duplicate values on UI.

 

Thanks

Ankit Arora

Blog | Facebook | Blog Page

Shashikant SharmaShashikant Sharma

When ever you add error in trigger on the records which are in processing your trigger ececution returns to the action which invoke the trigger rolling Back the results. Let me try to expalin with this example.

 

trigger exceptionHandling on Account (before insert) 
{
    for(Account a : trigger.new)
    {
       a.Name = ' test error name';
    }
    Contact c = new Contact(lastName = 'Test exceptionHandling rollBack');
    insert c;
    trigger.new[1].addError('Error');// Here I added a Error in index 1 item 
}

 Now I will write down a test methos as well

 

@isTest
private class TriggeErrorTest
{

    private static testmethod void testTriggerErrorM1()
    {
        List<Account> l = new List<Account>();
        try
        {
        Account a1 =  new Account(Name = 'Test TriggeErrorTest');
        Account a2 =  new Account(Name = 'Test TriggeErrorTest');
        
        l.add(a1);
        l.add(a2);
        insert l;
        }
        catch(Exception e)
        {
            
        }
        
        l = [Select Name from Account where id in: l];
        system.debug(' ******** l : ' + l);// This list will be empty
        system.debug('***** Contact :  ' + [Select Name, Id from Contact where lastName = 'Test exceptionHandling rollBack']);// This Contact Query will not return any rows
    
    }


}

 Even though I add error after Iterating over trigger.new I changed Account Name. Then I inserted contact and then I added error but still all changes will roll back. You will see no iAdding error here will throw a exception. Both debug will not sow any results(rows).Add error  will rollback all the action performed. Add error behaviour is like an excetion in Apex Code.

 

Please elaborate you requirement so that we can try to find a solution for it.

Rahul SharmaRahul Sharma

Hi,

 

I think you aren't avoiding duplicates properly.

See first query all the records, then take the records field which you dont want to duplicate in set.

then while inserting in list check if that string/Integer (whatever may the value of that field) then throw error.

 

I'll post here an example to be more clear:

 

trigger AvoidDuplicateAccounts on Account (before insert, before delete) 
{
  Set<String> setAccountName = new Set<String>(); 
  for(Account objAccount: [Select Name from Account])
    setAccountName.add(objAccount.Name);
  for(Account objAccount: Trigger.new)
    {
      if(!setAccountName.contains(objAccount.Name))
      {
	  setAccountName.add(objAccount.Name);
      }
      else
      {
	objAccount.Name.addError('Account with same name Exists');
      }
    }
}

 

James LoghryJames Loghry
Just came across this post when researching a similar issue.  Will have to try Ankit's approach, as I have struggled with addError in the past.  Thanks.