Как получить SOQL-запрос из цикла for - PullRequest
0 голосов
/ 18 ноября 2018

Код добавлен.

Я бесконечно искал решение и не могу его найти, пожалуйста, помогите!

У меня есть три объекта (A, B и C). A имеет поиск в B, а B является мастером в C (подробно). И A, и C имеют много записей, связанных с каждой B-записью.

Я хочу выполнить задание, которое получит подмножество записей из объекта C (обычно это будет около 5000 записей). Затем пройдитесь по каждому из них и получите записи в объекте A, которые обращаются к одной и той же записи объекта B, суммируйте числовое поле объекта A и поместите его в запись C.

Я успешно получил это для работы в небольшом масштабе, <100 записей объекта C. Но каждая запись Object C требует нового SOQL-запроса, так как я перебираю их в цикле for после получения всех записей Object C. Кроме того, я знаю, что это не лучшая практика - когда-либо иметь запрос в цикле. </p>

Как мне заставить это работать? Поскольку записи имеют отношение к объекту B, есть ли другой способ получить данные из соответствующих записей объекта A? Или есть какой-то способ вытащить два списка, один Объект C и один Объект A. Затем суммировать записи Объекта A и выстроить списки в ряд как?

Заранее спасибо!

Код:

public class nightlyJob {
    public static void updateNumbers(){
        integer I = 29; 
        List<ObjectC__c> CUpdateList = new List<ObjectC__c>();
        List<ObjectC__c> CpullList = 
                  [SELECT ID, Index__c, ObjectB__r.id
                  FROM ObjectC__c
                  WHERE Index__c = :I];
                for(ObjectC__c s : CpullList){
                        List<ObjectA__c> AList =
                            [SELECT ObjectB__c, Number__c
                            FROM ObjectA__c
                            WHERE ObjectB__c = :s.ObjectB__r.Id];
                    decimal NumSum = 0;
                    for(ObjectA__c a : AList){
                        NumSum = a.Number__c + NumSum;
                    }
                    s.Num__c = NumSum;
                    CUpdateList.add(s);
                }
        update CUpdateList;
    }            
}

1 Ответ

0 голосов
/ 19 ноября 2018

Похоже, что в настоящий момент вы действительно упускаете несколько фундаментальных понятий.

Самая большая проблема, с которой вы сталкиваетесь при разработке SFDC, заключается в том, что операции с "базами данных" очень дороги и строго ограничены.Дело не только в «наилучшей практике»: если в одной транзакции вы превысите эти ограничения - количество вызовов SOQL, количество возвращенных записей, количество обновленных записей, количество операторов DML и т. Д. - ваша транзакция завершится неудачно,Для получения дополнительной информации выполните поиск в Интернете по запросу «Регуляторы и ограничения Salesforce».

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

Во-первых, научитесь использовать коллекции с запросами SOQL, чтобы получить ваши запросы SOQL из циклов.Это также «массовая рассылка», и она фундаментальна для разработки SFDC:

    List<ObjectC__c> CpullList = 
              [SELECT ID, Index__c, ObjectB__r.id
              FROM ObjectC__c
              WHERE Index__c = :I];
    // Create a map with the results of this query.  
    // key=ObjectC__c.Id, value = Object__c record
    Map<Id, ObjectC__c> objCmap = Map<Id, ObjectC__c>(CpullList);

    // Build a set of all the Object_B id's from this result set
    Set<Id> objBids = new Set<Id>();
    for (ObjectC__c record : CpullList) {
        objBids.add(record.ObjectB__r.id);
    }

    // Now you can use only one SOQL query instead of a loop
    List<ObjectA> AList = [SELECT ObjectB__c, Number__c
                        FROM ObjectA__c
                        WHERE ObjectB__c in:objBids];

Далее, используйте «агрегатные функции SOQL», когда можете.Пример: в вашем коде вы можете использовать «SUM ()» и «group by» вместо выполнения этих вычислений с циклами:

    // Get the sum of ObjectA__c.Number__c for each Object B in objBIds
    AggregateResult[] groupedResults = [select ObjectB__c, 
                                        sum(Number__c) sumA 
                                        from ObjectA__c 
                                        where ObjectB__c in: objBids 
                                        group by ObjectB__c];

    for (AggregateResult ar : groupedResults)  {
        System.debug('Object B Id' + ar.get('Objectb__c'));
        System.debug('Sum of ObjectA__c.Number__c' + ar.get('sumA'));

        // Here, you might want to build a Map<Id, Integer> sumAmap:
        // key=Object B ID, value=sumA
        // and then use it along with objCmap to build a collection of Object C's 
        // for your update statement...
    }

Вы можете продолжить этот процесс и применить эти идеи для создания кодаболее эффективный.

Но даже после того, как ваши методы работают максимально эффективно, вы все равно можете столкнуться с ограничениями из-за количества записей, с которыми вы имеете дело.На этом этапе вам нужно будет изучить интерфейс Batchable, интерфейс Queuable и вызовы @future (как обрабатывать большее количество записей, распределенных по транзакциям). Это слишком много для информации, чтобы охватить ее в одном ответе SO.

...