У меня есть функциональное простое доказательство концепции триггера before insert, который использует настраиваемый тип метаданных для перевода значений полей на английский язык, которые заполняются из веб-форм, существующих на нескольких языках.

Теперь я делаю «правильно», перемещая логику в класс, но сталкиваюсь с неожиданными проблемами с этой ошибкой:

DML statement cannot operate on trigger.new or trigger.old

Другие сообщения предлагают создать экземпляр нового запись и установка идентификатора, но это приводит к другой ошибке, предположительно, потому что это триггер перед вставкой, а идентификатор еще не существует.

MISSING_ARGUMENT, Id not specified in an update call

Итак, я нахожусь в тупике - как мне обновить поля в записях в trigger.new в триггере перед вставкой при использовании класса вершины для логики?

Код триггера

trigger LeadBeforeInsert on Lead (before insert) {
 leadAction.translateVentureNomination(trigger.new);
}

Класс Apex (также не уверен, нужны ли мне статические методы или нет, но это отдельный вопрос)

public class leadAction {
    
    static list<Lead_Field_Translation_Mapping__mdt> tmapList = new list<Lead_Field_Translation_Mapping__mdt>([select label,english_value__c, local_value__c from Lead_Field_Translation_Mapping__mdt]);
    static map<string,string> tmap = new map<string,string>();
    
    public leadAction(){        
            for (Lead_Field_Translation_Mapping__mdt ftm : tmapList){
                tmap.put(ftm.local_value__c,ftm.english_value__c);
            }
    }
    
    public static void translateVentureNomination(list<lead> leads){            
        list<lead> updateList = new list<lead>();
        for (lead l : leads){ 
        //+add better error handling        
        if(tmap.get(l.Country_of_Election__c) == null){
            utils_logging.writeToLog('error translating country of election', 'lead before insert trigger');
        }
        else (l.country_of_election__c = tmap.get(l.Country_of_Election__c));

        list<string> tpopList = l.target_population__c.split(';');                
        string tpop = '';
        for(string s : tpopList){
            //system.debug('s = ' + s);            
            tpop += tmap.get(s.trim())+';';    
        }        
        l.target_population__c = tpop;
        updateList.add(l);
    }
        update updateList;
        
        
    }
}
1
Adrian Larson 14 Сен 2021 в 23:23

1 ответ

Лучший ответ

В BeforeTrigger вы можете изменить значение Lead напрямую и не выполнять DML, так как оно будет изменено. Итак, в вашем методе просто удалите updateList и оператор DML, и он будет работать.

Другая проблема заключается в том, что tmap будет пустым, поэтому у вас не будет правильных значений. Вы можете сделать свою карту статической (как есть) и заполнить ее непосредственно в своем методе, а не в конструкторе.

3
Luisma Whatakuai 14 Сен 2021 в 23:22
Спасибо за идею, я уже пробовал это, и мои тесты не увенчались успехом. Это отлично работало в самом триггере, но не тогда, когда я перенес логику в класс.
 – 
gorav
14 Сен 2021 в 23:06
1
Может быть две проблемы: первая заключается в том, что ваша карта не заполняется, поскольку метод является статическим, и вы не создаете экземпляр класса, чтобы конструктор не выполнялся. Другая проблема может заключаться в том, что существует другая логика, изменяющая значение этого поля после триггера или других автоматизаций.
 – 
Luisma Whatakuai
14 Сен 2021 в 23:20
Спасибо, это было так - статические вещи все еще сбивают меня с толку, теперь, когда вы это говорите, это имеет смысл. никаких операторов DML не требуется!
 – 
gorav
14 Сен 2021 в 23:28