0

I am trying to check duplicate lookup field values in a custom object named ABC__c. The lookup field is named RelatedUser__c and references the standard User object in Salesforce. Aside from this, there is another lookup field named Alphabet__c which references a custom object named Alphabet__c.

The rule is that there should be an error when RelatedUser__c already assigned to same Alphabet__c record is inputted to new ABC__c record.

I created an apex class and trigger to implement said requirement, but I am getting the following error:

System.FinalException: SObject row does not allow errors

I am kind of stuck right now and don't know what went wrong. How can I fix this?

ABCController

public with sharing class ABCController {
    public static void duplicateMethod() {
        List<Alphabet__c> alphabetList = new List<Alphabet__c>();
        List<ABC__c> abcList = new List<ABC__c>();

        alphabetList = [SELECT Id, Name FROM Alphabet__c];

        abcList = [SELECT Id, Name, Alphabet__c, RelatedUser__c FROM ABC__c
        WHERE Alphabet__c IN :alphabetList];

        for(ABC__c newABC : abcList) {
            for(ABC__c existingABC : abcList) {
                if(newABC.RelatedUser__c == existingABC.RelatedUser__c)  {
                    newABC.addError('related user is already assigned to same alphabet');
                }
            }
        }
    }
}

ABCTrigger

trigger ABCTrigger on ABC__c (before insert, before update) {
    ABCController.duplicateMethod();
}

I am quite grasping out the basic in Salesforce development but I hope I have clearly explained my issue here. Please bear with me.

1
  • I'm not having any luck trying to reproduce this error, but the error isn't the only issue with the code. If you're looking to prevent inserts from happening, you almost certainly want to be working on records contained in trigger.new (one of the trigger context variables).
    – Derek F
    Commented Dec 17, 2020 at 16:07

1 Answer 1

0

addError only works for sobject from trigger.new, so do this:

ABCController.duplicateMethod(trigger.new);

then fix your codes accordingly:

public with sharing class ABCController {
    public static void duplicateMethod(List<ABC__c> items) {

        Set<Id> users = new Set<Id>();
        Set<Id> alphabets = new Set<Id>();
        Map<String, List<ABC__c>> itemsByKey = new Map<String, List<ABC__c>>();
        for(ABC__c a: items) {
            String key = a.Alphabet__c + a.RelatedUser__c;
            users.add(a.RelatedUser__c);
            alphabets.add(a.Alphabet__c);

            if(!itemsByKey.containsKey(key)) {
                itemsByKey.put(key, new List<ABC__c>());
            }
            itemsByKey.get(key).add(a);
        }
        
        Set<String> keysInDB = new Set<String>();
        for(ABC__c a : [SELECT Id, Alphabet__c, RelatedUser__c  FROM ABC__c WHERE Alphabet__c IN :alphabets AND RelatedUser__c IN :users]) {
            keysInDB.add(a.Alphabet__c + a.RelatedUser__c);
        }

        for(String k: keysInDB) {
            if(!itemsByKey.containsKey(k)) continue;
            for(ABC__c a: itemsByKey.get(k)) {
                a.addError('Duplicate');
            }
        }
    }
}

For a good fix or best practice, continue your reading:

Create a custom field Alphabet_RelatedUser__c (text) and make it unique, external Id.

While creating new ABC__c record, set Alphabet_RelatedUser__c as Alphabet__c + RelatedUser__c.

ABC__c abc = new ABC__c(Alphabet__c = a, RelatedUser__c = u, Alphabet_RelatedUser__c = a + u);
upsert abc Alphabet_RelatedUser__c; 

if you want to error out at before insert trigger:

Set<String> keys = new Set<String>();
for(ABC__c a: trigger.new) {
   if(String.isBlank(a.Alphabet_RelatedUser__c) {
       a.Alphabet_RelatedUser__c = a.Alphabet__c + a.RelatedUser__c;
   }
   keys.add(a.Alphabet_RelatedUser__c);
}
Set<String> keysInDB = new Set<String>();
for(ABC__c a: [SELECT Alphabet_RelatedUser__c FROM ABC__c WHERE Alphabet_RelatedUser__c IN :keys]) {
    keysInDB.add(a.Alphabet_RelatedUser__c);
}

for(ABC__c a: trigger.new) {
   if(keysInDB.contains(a.Alphabet_RelatedUser__c)) {
      a.addError('Duplicate');
   }
}
1
  • Thanks for your immediate response, but can't it be done using the existing SOQL I have? Also, is trigger.new allowed inside a handler class? Commented Dec 17, 2020 at 16:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .