У меня есть Object Alpha и Object Num с полями A, B, C и 1,2,3 соответственно. Я должен написать триггер на обоих объектах

  • когда поле A в Object Alpha обновляется, поле 1 в Object Num должно быть обновлено, и наоборот.
  • Точно так же, когда поле B в Object Alpha обновляется, поле 2 в Object Num должно быть обновлено, и наоборот.
  • Точно так же, когда поле c в Object Alpha обновляется, поле 1 в Object Num должно быть обновлено, и наоборот.

Как избежать рекурсивного срабатывания (когда поле A обновляет поле 1, а затем не срабатывает триггер на Object Num для обновления поля A на Object Alpha, который снова запускает обновление поля ....) Любые входные данные?

0
David Cheng 9 Ноя 2019 в 04:05
1
Связаны ли объект альфа и номер объекта? Каковы отношения?
 – 
David Cheng
9 Ноя 2019 в 04:06

2 ответа

Лучший ответ

Защита рекурсии очень сложна. Использование простого статического логического значения является плохой практикой: существует множество причин, по которым ваш триггер может срабатывать более одного раза за транзакцию, а использование логического значения в стиле runOnce означает, что ваш триггер просто молча ничего не делает в этих случаях. Это часто приводит к сложному для отладки поведению.

Вместо этого используйте статические логические значения, которые относятся к одному оператору DML, например.


class TriggerContext {
    static Boolean isUpdatingOtherObject = false;
}

trigger SomeTrigger on Object_A__c (after update) {
    if (!TriggerContext.isUpdatingOtherObject) {
        TriggerContext.isUpdatingOtherObject = true;
        update [SELECT Id FROM Object_B__c ...];
        TriggerContext.isUpdatingOtherObject = false;
    }
}

trigger AnotherTrigger on Object_B__c (after update) {
    if (!TriggerContext.isUpdatingOtherObject) {
        TriggerContext.isUpdatingOtherObject = true;
        update [SELECT Id FROM Object_A__c ...];
        TriggerContext.isUpdatingOtherObject = false;
    }
}

Обратите внимание, что защита от рекурсии активна только во время операции DML с другим объектом в паре. Это гарантирует, что оба триггера срабатывают именно тогда, когда это необходимо, но не срабатывают в ответ на обновления друг друга.

2
David Reed 9 Ноя 2019 в 08:20

Вы можете создать такой помощник

public class ContactTriggerHelper {public static Boolean runOnce = true;
                                   public static void onAfterUpdate(List<Contact> newacc){
         for(Integer i=0;i<newacc.size();i++)
         {
       insert (new Account(Name='Test'+i));
        runOnce = true;
        System.debug('Is After Update');
         }}

}

А затем в триггере вы можете проверить

  if(Trigger.isAfter  && ContactTriggerHelper.runOnce){
         ContactTriggerHelper.runOnce = false;
        ContactTriggerHelper.onAfterUpdate(Trigger.New);
    }

Создать то же самое для других объектов тоже

0
User6670 8 Ноя 2019 в 09:35
Не мог бы тот, кто проголосовал против, объяснить, почему они проголосовали за этот ответ, чтобы люди знали, почему он плохой?
 – 
Phil W
9 Ноя 2019 в 11:24