Здравствуйте!
сегодня писал тригер на афтер апдейт, который создает запись, если изменилось значение в поле Пример на Завершено в другой записи. Так вот, тригер создает две идентичные записи подряд.
Не успел подебагить: либо тригер в целом срабатывает дважды, либо главный цикл тригера по каким то причинам делает два оборота (новая запись не вставляется в главном цикле, в нем собирается лист новых записей, и вне цикла они вставляется за один инсерт). Нужно еще проверить, что именно происходит.
К слову на изменение значения в поле Пример на Завершено должен срабатывать Ворк Флоу и менять другое поле в данной записи. Неужели он провоцирует повторную сработку тригера? но в условия тригера есть ("Завершено" !=Trigger.oldMap.get(Объект.Id).Пример__c), те он не должен срабатывать после какого-либо обновления (спровоцированного ВоркФлоу) если в поле Пример уже было значение "Завершено" . Кроме того и сам тригер на афтер апдейт, те тот ВоркФлоу который я подозреваю должен сработать до тригера.... Буду разбираться.
Большая вероятность того, что у тебя триггер срабатывает дважды.
Это легко проверить - поставь в самом начала триггера SYSTEM.DEBUG('some trigger fired');
и посмотри в debug log. Сколько записей найдешь, столько раз у тебя сработал триггер.
На счет одновременной работы воркфлов и триггера это уже тяжелый случай. Лучше так не делать. Либо одно, либо другое. Иначе будут проблемы.
А так тебе в помощь только debug log поможет. Учись его читать
В общем на счет многократного срабатывания триггера - есть такой тип проблемы. Раньше пару раз сталкивался. Если это не связано с кривым кодом, а просто по логике так получается, то есть кастыль на этот случай. Надо сделать статический класс со статической переменной и выставлять в ней какое-нибудь значение при входе в триггер. И опять же в триггере проверять это значений. Если значение в статической переменной найдено, то это говорит о том, что триггер уже сработал и повторный его запуск можно отменять.
Все так и было Дмитрий.
Вот только на прошлых выходных я прочел об этом в книге Дена Аплмена, о том что специфика разработки в SFDC в том, что разработчик знает когда ран контекст начинается, но никогда не знает когда данный конкретный ран контектс закончится - так на него влияют WFR - которые настраивают админы системы, не разработчики - а дествия этих WFR может привести к повторной сработке тригера в пределах одного ран контекста.
И вот оно.
Нужен класс со статик переменной.
Статик переменный объявленные внутри тригера не живут весь ран контектс.
Так точно я для этого использую ENV класс, который всегда знает что сейчас выполняется
А как это работает?
я создал:
public class StaticHelper {
public static integer helper;
}и вначале тригера - проверка значение в helper
и в конце тригера
StaticHelper.helper=1;
и для каждого тригера нужно создавать свой вспомогательный класс или добавлять в существующий новое статичное поле
книга физическая, не электронная.
могу на работе читать, но не могу никаким образом копировать - права, права...
по мере прочтения - могу делится светлыми мыслями, почерпнутыми из нее, на форуме.
Вот и сама книжка на амазоне:
[url]http://www.amazon.com/Advanced-Apex-Programming-Salesforce-com-Force-com/dp/1936754053" rel="nofollow" target="_blank">http://www.amazon.com/Advanced-Apex-Programming-Salesforce-com-Force-com/dp/1936754053" rel="nofollow" target="_blank">
[url]http://www.amazon.com/Advanced-Apex-Programming-Salesforce-com-Force-com/dp/1936754053
Вот мой вариант.
Пример использования :
trigger TRGR_Contact on Contact (before insert, before update) {
Integer Cnt = Env.setTriggersRun(true,null);
if (Trigger.isBefore && Trigger.isInsert) {
HNDL_Contact.setHistory(trigger.New, null);
}
if (Trigger.isBefore && Trigger.isUpdate) {
HNDL_Contact.setHistory(trigger.New, trigger.oldMap);
}
Env.setTriggersRun(false, Cnt);
}
Сам класс в приложении. [Расширение cls запрещено администратором.] это еще почему ?
Log example :
[0][START] OpportunityLineItem [BEFORE : UPDATE](1)
[0][END] OpportunityLineItem [BEFORE : UPDATE] SOQL Count : [0] (1)
[0][START] OpportunityLineItem [AFTER : UPDATE](1)
[1][START] Forecast_Line__c [BEFORE : UPDATE](3)
[1][END] Forecast_Line__c [BEFORE : UPDATE] SOQL Count : [3] (3)
[1][START] Yearly_Quota__c [BEFORE : UPDATE](1)
[1][END] Yearly_Quota__c [BEFORE : UPDATE] SOQL Count : [4] (1)
[1][START] Yearly_Quota__c [AFTER : UPDATE](1)
[1][END] Yearly_Quota__c [AFTER : UPDATE] SOQL Count : [5] (1)
[0][END] OpportunityLineItem [AFTER : UPDATE] SOQL Count : [1] (1)
[0][START] OpportunityLineItem [BEFORE : UPDATE](1)
[0][END] OpportunityLineItem [BEFORE : UPDATE] SOQL Count : [1] (1)
[0][START] OpportunityLineItem [AFTER : UPDATE](1)
[1][START] Forecast_Line__c [BEFORE : UPDATE](3)
[1][END] Forecast_Line__c [BEFORE : UPDATE] SOQL Count : [8] (3)
[0][END] OpportunityLineItem [AFTER : UPDATE] SOQL Count : [2] (1)
[0][START] Opportunity [BEFORE : UPDATE](1)
[0][END] Opportunity [BEFORE : UPDATE] SOQL Count : [2] (1)
[0][START] Opportunity [AFTER : UPDATE](1)
[0][END] Opportunity [AFTER : UPDATE] SOQL Count : [3] (1)
Count RUNS : 10
Сам класс в приложении. [Расширение cls запрещено администратором.] это еще почему ?
Пока не знаю, по видимому дефолтные настройки форума. Исправлю.
Появилась неожиданная проблема.
Со слов коллег, они не могут установить деплой сет с тригером и классом со статичной переменной в другой орг. Выдается ошибка, что такой (статичной) переменной не существует (хотя они клянутся, что отгрузили этот вспомогательный класс в сет).
КРоме того уже вижу, что они покрыли тестом тригер который использует эту стат переменную на 100%, а покрытие этого класса со статичной переменной в исходящем орге при это 0%. Как это может быть.
Но главная проблема именно с переносом - толи они что-то не так делают, то ли с переносом кода использующего стат переменные действительно какие-то проблемы....
PS а нет - сделали они деплой, при чем не могут объяснить, что они сделали :)
мне кажется что кто-то что-то не договаривает (намекаю на "тех")
Никаких проблем со статической переменной не должно и не может быть. По всей вероятности не включили в changeSet класс.
:) мне кажется что кто-то что-то не договаривает (намекаю на "тех")Никаких проблем со статической переменной не должно и не может быть. По всей вероятности не включили в changeSet класс.
Или тесты валятся на Exception каком-либо.
Все отгрузили они. Но не признаются, что сделали.
Ну ладно - нет проблем со стат переменными при переносе - и здорово.
Но вот почему тригер покрыт на 100%, а класс с одной единственной переменной, которую он использует - покрыт на 0% - я не знаю.