Trigger Record Creation funktioniert nicht in Bulk Update [Duplikat]

Nov 20 2020

Wir haben einen Prozess, bei dem Datensätze, die mit Sync_Prospect_to_Pardot__c auf true aktualisiert werden, für jeden aktualisierten Datensatz einen pi__ObjectChangeLog__c-Datensatz erstellen sollten. Wenn ich jedoch den Datenlader zum Aktualisieren von 250 Datensätzen mit aktivierter Massen-API verwende, werden nur 200 pi__ObjectChangeLog__c-Datensätze erstellt. Wenn ich diese Einstellung deaktiviert habe, werden alle 250 erstellt. Ich habe ein Ticket mit Salesforce-Support angemeldet und sie sagten, es sei kein Problem mit dem Datenlader, und sie geben kein Feedback zum Code, da dieser außerhalb des Gültigkeitsbereichs liegt. Die Pardot-Unterstützung war nicht hilfreich, da wir einen benutzerdefinierten Prozess zum Erstellen der Objektänderungsprotokolle verwenden. Hier ist eindeutig etwas los und der Code unterscheidet sich nicht von dem, was ich für den Rest der Organisation geschrieben habe. Wir sehen keine Probleme bei der Verwendung von Bulk-API, um einen dieser Prozesse auszulösen.

Das pi__ObjectChangeLog__c-Objekt ist als "Massen-API-Zugriff zulassen" gekennzeichnet.

Ist das Problem der Code? Wenn nicht, welche anderen Dinge muss ich überprüfen? Ich erhalte die gleichen Ergebnisse, unabhängig davon, ob es sich bei dem Startobjekt um einen Kontakt oder einen Lead handelt.

Hier sind die Komponenten. Beachten Sie, dass wir das von Trailhead empfohlene SFDC Trigger Framework von Kevin O'Hara verwenden .

Auslösen

trigger LeadTrigger on Lead (before insert, before update, before delete, after insert, after update, after delete, after undelete) {
    Map<String, Trigger_Settings__c> triggerSettings = Trigger_Settings__c.getAll();
    
    if(triggerSettings.get('LeadTrigger') <> null && triggerSettings.get('LeadTrigger').Execute_Trigger__c)
        new LeadTriggerDispatcher().run();
}

Dispatcher

public without sharing class LeadTriggerDispatcher extends TriggerHandler {
//Trigger context variables are still available but need to be cast: trigger.new, trigger.newMap, trigger.oldMap
    List<Lead> leads = (List<Lead>) trigger.new;
    Map<Id, Lead> leadsOldMap = (Map<Id, Lead>) trigger.oldMap;
    Map<Id, Lead> leadsNewMap = (Map<Id, Lead>) trigger.newMap;
    Map<String, Trigger_Settings__c> triggerSettings = Trigger_Settings__c.getAll();

    protected override void afterUpdate() {
        //declare variables
        Set<sObject> leadsForSync = new Set<sObject>();

        //loop through to find qualifying records
        for(Lead lead : leads) {
            //leads are eligible for sync if their sync to prospect field changes, but no email changes were made. By default an OCL gets created if the email is updated
            if(leadsOldMap.get(lead.Id).Sync_Prospect_to_Pardot__c == false && leadsNewMap.get(lead.Id).Sync_Prospect_to_Pardot__c == true)
                leadsForSync.add((sObject)lead);
        }

        //execute methods
        if(!leadsForSync.isEmpty() && !TriggerHandler.isBypassed('PardotSyncManager') && triggerSettings.get('PardotSyncManager') <> null && triggerSettings.get('PardotSyncManager').Execute_Trigger__c) {
            TriggerHandler.bypass('PardotSyncManager');
            PardotSyncManager.createObjectChangeLog(leadsForSync);
        }
    }
}

Klasse

public without sharing class PardotSyncManager {
    //createObjectChangeLog takes a set of lead or contact records and creates an OCL record for those records. Called from the contact or lead dispatcher
    public static void createObjectChangeLog(Set<sObject> records) {
        system.debug('PardotSyncManager Start');

        system.debug('records size: ' + records.size());

        //oclsForInsert stores a list of OCLs that need to be inserted
        List<pi__ObjectChangeLog__c> oclsForInsert = new List<pi__ObjectChangeLog__c>();

        //Iterate through all records in the scope
        for(sObject record : records) {
            system.debug('record Ids: ' + record.Id);
            //Check if the record is a contact. If so, then parse the sObject to a contact and then create an OCL for that contact.
            if(String.valueOf(record.Id).substring(0,3) == '003') {
                Contact contact = (Contact)record;
                oclsForInsert.add(new pi__ObjectChangeLog__c(pi__ObjectEmail__c = contact.Email, pi__ObjectFid__c = contact.Id, pi__ObjectType__c = 1, pi__ObjectState__c = 1));
            }
            //Check if the record is a lead. If so, then parse the record into a lead and then create an OCL for that lead.
            else if(String.valueOf(record.Id).substring(0,3) == '00Q') {
                system.debug('lead qualified');
                Lead lead = (Lead)record;
                oclsForInsert.add(new pi__ObjectChangeLog__c(pi__ObjectEmail__c = lead.Email, pi__ObjectFid__c = lead.Id, pi__ObjectType__c = 2, pi__ObjectState__c = 1));
            }
        }

        //try to insert the OCL records
        try {
            system.debug('ocls for insert: ' + oclsForInsert.size());
            insert oclsForInsert;
        }
        //If there's an error, post the error to the debug log
        catch(Exception e) {
            system.debug('EXCEPTION in PardotSyncManager.createObjectChangeLog at row ' + e.getLineNumber() + ': ' + e.getMessage());
        }

        system.debug('PardotSyncManager Complete');
    }
}

Antworten

1 HR Nov 20 2020 at 03:52

TriggerHandler.isBypassed wird im Triggercode referenziert, um zu überprüfen, ob es bereits ausgeführt wurde oder nicht.

Die Massen-API verarbeitet jedoch alle Datensätze unter einer Transaktion, was bedeutet, dass die statischen Variablen niemals zurückgesetzt werden.

Bitte beziehen Sie sich auf diese - Bulk-API und Static Variable State

MarkPond Nov 20 2020 at 03:55

Sie müssen den Bypass in Ihrem Dispatcher löschen, sobald die PardotSyncManagerAusführung des Codes abgeschlossen ist.

Lassen Sie Ihren if-Block stattdessen effektiv so aussehen:

//execute methods
if (
  !leadsForSync.isEmpty() &&
  !TriggerHandler.isBypassed('PardotSyncManager') && // this is causing it to only run on the first iteration
  triggerSettings.get('PardotSyncManager') <> null &&
  triggerSettings.get('PardotSyncManager').Execute_Trigger__c
) {
  // turn off the trigger handler
  TriggerHandler.bypass('PardotSyncManager');

  // do the work
  PardotSyncManager.createObjectChangeLog(leadsForSync);

  // turn the trigger handler back on
  TriggerHandler.clearBypass('PardotSyncManager'); // because this bypass removal was not here
}