4

I am trying to create a trigger that would add a new value to a related list if a value is adeded to a field.

The field is called Reason of Contact (ROC) and when ever a new reason of contact is added or the field is populated it brings the new value to the related list in the Case. This is working correctly but when ever the first reason of contact is added to the case this value is entered twice. But after that everything works fine. So can someone see what is wrong with the code so that it would not create a duplicate value if the list for Reason Of Contacts (ROCs) is empty.

//


trigger createROCchildonCaseUpdate on Case (after update) {

// Create an empty list of String
List<Reasons_of_Contact__c> ROCs = new List<Reasons_of_Contact__c>();

    //For each case processed by the trigger, add a new  

    //ROC record for the specified case.  

    //Note that Trigger.New is a list of all the new positions  

    //that are being created.  

    for (Case newCase : Trigger.new) {
    Case oldCase = Trigger.oldMap.get(newCase.Id);
    if (oldCase.Request_3__c != newCase.Request_3__c | oldCase.Request_3__c != NULL) {

         //Create the new ROC in the related list with the following values
               ROCs.add(new Reasons_of_Contact__c(
                        ProgramCaseLink__c = newCase.Id,
                        Type__c = newCase.Request_3__c,
                        ProgramCommentLookup__c = newCase.Program__c));
        }
    }
    insert ROCs;
}
6
  • 2
    You have a bitwise or "|" where you probably intended a logical or "||". I'd start by fixing that.
    – Keith C
    Nov 29 '13 at 9:30
  • Thanks @KeithC This is now fixed but still the same result. Nov 29 '13 at 9:37
  • to add with what @KeithC has mentioned, check if there is any other workflow/trigger which is updating the case again. Maybe add a debug statement to see how many are there on ROCs
    – Prady
    Nov 29 '13 at 9:38
  • Thanks @Prady but it seems strange that the duplicate value comes only if there is now value present. So it created duplicate values only if the list is empty. So it does not seem to be the case of other triggers running at the same time. I have also tested this by disabling all other triggers and still get the same results. Nov 29 '13 at 9:48
  • 1
    Is there a workflow or trigger on the ROC custom object that makes DML statements? This is generally the cause of something like this. Even if they do not make the DML call directly on the Case object, it could be causing a chain of wroflows and/or triggers that eventually makes a change to the Case object which would cause your trigger to fire again Nov 29 '13 at 14:27
1

While it's not immediately obvious, it's important to know that you're trigger can run multiple times. The primary cause is a workflow field update which causes all triggers for an object to get re-evaluated a second time Based on your description it sounds like the field update is only set to fire when a record is created.

Even less obvious is that after the field update trigger.old contains the same values from the start of the transaction. So if you start with "Foo", change it to "Bar", then a field update causes a second trigger execution, trigger.old still contains "Foo".

To get things to work the way you want, move you're logic into an external class and use a static map to record the last value you saw for the field. That way the second trigger execution won't generate a duplicate record unless the field truly changed.

public class MyProcessor {

  private static Map<Id, Case> oldMapOverride = new Map<Id, Case>();

  public static void execute() {
    List<Reason_of_Contact__c> ROCs = new List<Reason_of_Contact__c>();

    for(Case newCase : trigger.new) {

      // if we've seen this case before, get it from the override map
      Case oldCase = (oldMapOverride.containsKey(newCase.id)) 
        ? oldMapOverride.get(newCase.id) : trigger.oldMap.get(newCase.id);

      // has something changed?
      if (
        oldCase == null ||
        oldCase.Request_3__c != newCase.Request_3__c || 
        oldCase.Request_3__c != NULL
      ) {

        //Create the new ROC in the related list with the following values
        ROCs.add(new Reasons_of_Contact__c(
          ProgramCaseLink__c = newCase.Id,
          Type__c = newCase.Request_3__c,
          ProgramCommentLookup__c = newCase.Program__c));

        // Store this record in case we see it again
        oldMapOverride.put(newCase.id, newCase);
      }
    }

    inserts ROCs;
  }
}
1
  • 1
    Excellent answer. Here's the Triggers and Order of Execution docs, for reference. The last bullet point is relevant: When a record is updated and subsequently triggers a workflow rule field update, Trigger.old in the last update trigger won’t contain the version of the object immediately prior to the workflow update, but the object before the initial update was made. Nov 30 '13 at 0:31

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.