Переменная контекста триггера Apex

Вот мой код для триггера вершины.

trigger LeadTrigger on Lead (after insert) 
{
      if(Trigger.isInsert){
             for(Lead newLead: Trigger.new)
             {
                 //newLead.RecrodTypeId  //'Give value of record type id.
                 //newLead.RecordType.Name //'Null'
             }
      }
}

Почему «newLead.RecordType.Name» возвращает значение null?


person chandreshkoyani    schedule 09.12.2011    source источник


Ответы (4)


Списки объектов, доступных в триггерах, содержат значения только для полей объекта, над которым работает триггер. Никакие отношения не просматриваются, включаются только идентификаторы записей поиска.

Следовательно, для получения любой дополнительной информации, необходимой для связанных объектов, необходимо запросить ее.

Вы захотите сделать что-то вроде этого:

trigger LeadTrigger on Lead (after insert) {

    map<id, RecordType> mapRecordTypes = new map<id, RecordType>();

    if(Trigger.isInsert) {
        for(Lead newLead: Trigger.new) {
            mapRecordTypes.put(newLead.RecordTypeId, null);
        }
    }

    for(RecordType rt : [select Id, Name from RecordType
                           where Id in : mapRecordTypes.ketSet()]) {
        mapRecordTypes.put(rt.Id, rt);
    }

    for(Lead newLead : Trigger.new) {
        string recordTypeName = mapRecordTypes.get(sLead.RecordTypeId).Name;
    }
}
person Matt Lacey    schedule 13.12.2011
comment
Хороший чистый код Лейси. Мне нравится «нулевой шаг» вашей карты, чтобы избежать дополнительного цикла списка. - person Adam; 14.12.2011
comment
Спасибо, не мой обычный стиль брекетов, но я старался следовать стилю ОП. Только что понял, что он использовал оба! - person Matt Lacey; 14.12.2011
comment
Насколько я знаю, первоначальной причиной соглашения о наличии фигурных скобок справа и снизу была экономия на видимой недвижимости. Теперь, когда наши мониторы стали больше, мы можем выровнять их по левому краю, поскольку таким образом глаза отслеживают кодовые блоки намного быстрее. Обратите внимание, как далеко нужно перемещаться вашим глазам, чтобы прочитать чужой код, когда фигурные скобки выровнены справа и снизу. Но я отвлекаюсь на священную войну, которая бушует по сей день... (cboard.cprogramming.com/general-discussions/) - person Adam; 16.12.2011
comment
Ха-ха, я полностью на вашей стороне — мы больше не ограничены 25-строчными дисплеями! У меня всегда была моя на новой строке, намного легче читать ИМО. - person Matt Lacey; 16.12.2011

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

[РЕДАКТИРОВАТЬ]

Теперь я думаю, что понимаю проблему (из вашего комментария). Причина в том, что, поскольку вы находитесь в триггере, связанный объект RecordType ссылка недоступен. RecordTypeId всегда будет доступен, поскольку он буквально является частью объекта триггера в качестве идентификатора. Однако дочерние объекты (объекты, на которые ссылаются) не будут доступны для простой ссылки из триггера. Для этого вам необходимо создать карту рассматриваемого объекта, на который ссылаются, выполнив дополнительный вызов SOQL WHERE Id IN: theIdList.

Из Apex, а не из триггера, вам нужно специально вызвать это поле из вашего SOQL следующим образом:

List<Lead> leads = [SELECT Id, RecordType.Name FROM Lead];

Только что произошло то, что дочерний объект, в данном случае RecordType, был включен в запрос и, следовательно, доступен для вас. По умолчанию в триггере не будут предварительно выбраны все ваши дочерние объекты, и поэтому их необходимо будет выбрать впоследствии из триггера или класса, вызываемого триггером:

List<Id> recIds = new List<Id>();
for(Lead l : leads)
{
   recIds.add(l.RecordTypeId);
}

List<RecordType> rt = [SELECT Id, Name FROM RecordType WHERE Id IN :recIds];
Map <Id, String> idRecNameMap = new Map<Id, String>();
for(RecordType r : rt)
{
   idRecNameMap.put(r.Id, r.Name);
}

// And finally...
for(Lead l : Trigger.new)
{
   String tmpRecordTypeName = idRecNameMap.get(l.RecordTypeId);
}

Я не тестировал этот код, но думаю, что он выглядит нормально. Надеюсь, это имеет смысл.

person Adam    schedule 10.12.2011
comment
Оператор newLead.RecrodTypeId дает значение идентификаторов. Но newLead.RecordType.Name имеет значение null. Почему это так? Это будет происходить только в контексте жизненного цикла триггера (метод триггера и класса, который вызывается при срабатывании триггера). Но когда мы использовали этот оператор в обычном классе вершины. Тогда оба утверждения будут в порядке. - person chandreshkoyani; 13.12.2011

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

List<RecordType> records = [SELECT Id, Name FROM RecordType WHERE Id = newLead.RecrodTypeId];
string myname = records[0].name;

но помните, что вы не должны выполнять запрос в цикле for. поэтому, если вы хотите сделать это правильно, воспользуйтесь решением Адама.

person Daniel    schedule 04.06.2015

Поместите некоторую системную отладку в цикл и проверьте журналы отладки вашей системы для получения дополнительной информации.

system.debug('lead:' + newLead);

внутри цикла for и посмотрите, что передается. Вы можете обнаружить, что это null.

Мы не можем дать вам хороший ответ, не зная остальной части вашей установки.

person c14kaa    schedule 09.12.2011
comment
В приведенном выше коде я пишу, что System.debug(Id:- +newLead.RecrodTypeId) даст мне идентификаторы RecordType, связанные с лидом. Но нам нужно имя RecordType, поэтому я пытаюсь написать System.debug(Id:- +newLead.RecordType.Name), это вернет нулевое значение. - person chandreshkoyani; 13.12.2011