Ошибка Salesforce Apex: SELF_REFERENCE_FROM_TRIGGER - PullRequest
1 голос
/ 09 сентября 2011
Error: Invalid Data. 
Review all error messages below to correct your data.
Apex trigger triggerOpportunityCloseInstallDateChange caused an unexpected exception, contact your administrator: triggerOpportunityCloseInstallDateChange: execution of BeforeUpdate caused by: System.DmlException: Delete failed. First exception on row 0 with id 00o30000003ySNhAAM; first error: SELF_REFERENCE_FROM_TRIGGER, Object (id = 0063000000i23T9) is currently in trigger triggerOpportunityCloseInstallDateChange, therefore it cannot recursively update itself: []: Class.OpportunitySchedule.BuildScheduleAndUpdateDates: line 17, column 5

Я получаю вышеуказанную ошибку, когда пытаюсь извинить приведенный ниже код.Это мой второй день на земле APEX, так что со мной все в порядке.

У меня есть триггер на «до» возможности.Затем он вызывает приведенный ниже класс с помощью trigger.new.

public with sharing class OpportunitySchedule {

    public static void BuildScheduleAndUpdateDates(List<Opportunity> OpportunityList) {

        for (Integer i = 0; i < OpportunityList.size(); i++)
        {
            Opportunity opp_new = OpportunityList[i];

            List<OpportunityLineItem> lineItems = [Select o.Id, (Select OpportunityLineItemId From OpportunityLineItemSchedules), o.System_Add_on__c, o.ServiceDate, o.Schedule_Length__c , o.Monthly_Quantity__c, o.Monthly_Amount__c
                                                From OpportunityLineItem o
                                                where o.Opportunity.Id =  :opp_new.Id];

            for (OpportunityLineItem item : lineItems)
            {
                item.ServiceDate = opp_new.CloseDate;
                update item;
                delete item.OpportunityLineItemSchedules;       
            }                                   
        }
    }
}

Я пытаюсь удалить все расписания позиций, когда кто-то редактирует возможность.Странно то, что я могу удалить элемент delete.OpportunityLineItemSchedules и код запускается, он обновит элемент.Я не понимаю, почему удаление потомков childs (Opportunity -> OpportunityLineItem -> OpportunityLineItemSchedule) приведет к рекурсивному циклу.

Я попытался выполнить приведенный ниже код в этой ссылке, но не повезло:1010 *

Я также закомментировал все остальные триггеры, чтобы убедиться, что один из них не вызывает его.

Кто-нибудь знает, что я делаю не так?

Ответы [ 2 ]

1 голос
/ 13 мая 2012

Я не понимаю, почему удаление потомков потомков (OpportunityLine> OpportunityLineItem -> OpportunityLineItemSchedule) может вызвать рекурсивный цикл.

При использовании расписаний доходов TotalPrice для родительского OpportunityLineItemобновляется на основе связанных OpportunityLineItemSchedules.Поэтому, когда вы удаляете записи OpportunityLineItemSchedule, вы эффективно обновляете OpportunityLineItem, что вызывает исключение DML SELF_REFERENCE_FROM_TRIGGER.

См. Влияние на элементы возможностей и строки возможностей в документации OpportunityLineItemStem*

Удаление OpportunityLineItemSchedule аналогично влияет на связанные OpportunityLineItem и Opportunity.Удаление OpportunityLineItemSchedule уменьшает значение OpportunityLineItem TotalPrice на удаленное количество OpportunityLineItemSchedule или сумму дохода.Сумма возможностей также уменьшается на количество или доход OpportunityLineItemSchedule, а ожидаемый доход OpportunityLine уменьшается на количество или доход OpportunityLineItemSchedule, умноженное на вероятность вероятности.

1 голос
/ 10 сентября 2011

Несколько вещей, которые я заметил. Во-первых, никогда не помещайте DML в цикл, особенно в триггер. Чтение здесь о громоздких триггерах поможет: http://www.salesforce.com/us/developer/docs/apexcode/index_Left.htm#StartTopic=Content/apex_triggers.htm

В вашем коде вы почти на месте. Вместо обновления в цикле, просто обновите весь список после цикла:

for (OpportunityLineItem item : lineItems)
{
   item.ServiceDate = opp_new.CloseDate;
   //update item;
   //delete item.OpportunityLineItemSchedules;       
}

update lineItems;

Тогда вы создадите новый список только OpportunityLineItemSchedules, который имеет ParentId == OpportunityLineItem.Id. Затем вы удалите весь этот список одним вызовом:

delete saidList;

Что касается рекурсии, в отношениях мастер-детали Force.com автоматически обработает удаление дочерних элементов. Не так в поиске, где вам нужно удалить их вручную. Несмотря на то, что я не совсем уверен насчет OpportunityLineItemSchedules, я бы попробовал либо начать все с помощью триггера AFTER, либо использовать вспомогательный класс, который ваш поток триггера хранит в памяти, чтобы гарантировать, что, попав внутрь вашего класса обработчика триггера, он не будет введите его снова.

К сожалению, все, что я мог рассказать, - это все, что я хотел сказать Удачи и добро пожаловать в программирование Force.com. Надеюсь, что это растет на вас.

...