Vermeiden Sie die Verwendung von Batch-Requesttypen in Plugins und Workflow-Aktivitäten

Kategorie: Nutzung, Zuverlässigkeit, Leistung, Verfügbarkeit

Wirkungspotential: Mittel

Symptome

Wenn Sie Batch-Anforderungstypen in Plug-Ins und Workflow-Aktivitäten verwenden, die innerhalb synchroner Vorgänge auftreten, wird die Benutzererfahrung beeinträchtigt und es können Timeout-Fehler auftreten.

Die folgenden Nachrichtenanforderungsklassen gelten als Batch-Anforderungstypen, da sie Vorgänge für mehrere Datensätze innerhalb einer einzelnen Anforderung ausführen:

Anweisungen

Verwenden Sie diese Batch-Nachrichten in Client-Anwendungen, um Vorgänge für mehrere Datensätze auszuführen. Verwenden Sie diese Nachrichten nicht in Code, der in Dataverse während der Ausführung eines anderen Vorgangs aufgerufen wird: ein Plug-In oder eine Workflowaktivität, das für einen synchronen Schritt registriert ist.

Genauer gesagt, verwenden Sie sie in den folgenden Szenarien:

  • Verwenden Sie ExecuteMultipleRequest, um Daten oder externe Prozesse, die beabsichtigt sind, lang laufende Operationen durchzuführen (länger als zwei Minuten), in großen Mengen zu erfassen.

  • Verwenden Sie ExecuteMultipleRequest, um die Roundtrips zwischen dem benutzerdefinierten Client und Dataverse-Servern zu minimieren, um die kumulative Latenzzeit zu reduzieren.

  • Verwenden Sie ExecuteTransactionRequest für externe Clients, die verlangen, dass der Stapel von Operationen als einzelne, atomare Datenbanktransaktion oder Rollback übertragen wird, wenn eine Ausnahme auftritt. Beachten Sie das Potenzial einer Datenbanksperre für die Dauer der lang laufenden Transaktion.

  • Verwenden Sie Massenvorgangsnachrichten (CreateMultipleRequest, UpdateMultipleRequest und UpsertMultipleRequest) für dieselben Szenarien und um einen höheren Durchsatz zu erreichen.

Problematische Muster

Das folgende Beispiel zeigt die Verwendung von ExecuteMultipleRequest im Kontext eines Plug-Ins.

Warnung

Dieses Szenario sollte vermieden werden.

public class ExecuteMultipleRequestInPlugin : IPlugin
{
    public void Execute(IServiceProvider serviceProvider)
    {
        IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
        IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
        IOrganizationService service = factory.CreateOrganizationService(context.UserId);

        QueryExpression query = new QueryExpression("account")
        {
            ColumnSet = new ColumnSet("accountname", "createdon"),
        };

        //Obtain the results of previous QueryExpression
        EntityCollection results = service.RetrieveMultiple(query);

        if (results != null && results.Entities != null && results.Entities.Count > 0)
        {
            ExecuteMultipleRequest batch = new ExecuteMultipleRequest();
            foreach (Entity account in results.Entities)
            {
                account.Attributes["accountname"] += "_UPDATED";

                UpdateRequest updateRequest = new UpdateRequest();
                updateRequest.Target = account;

                batch.Requests.Add(updateRequest);
            }

            service.Execute(batch);
        }
        else return;

    }
}

Dieses Beispiel beinhaltet die Verwendung des Typs direkt mit der Methode Execute. Die Verwendung kann überall im Rahmen der Ausführung eines Plugins oder einer Workflow-Aktivität erfolgen. Dies kann auch in einer Methode sein, die in derselben oder einer separaten Klasse enthalten ist. Sie ist nicht darauf beschränkt, direkt in der Execute-Methodendefinition enthalten zu sein.

Weitere Informationen

Das Ziel der ExecuteMultiple-Nachricht ist es, Roundtrips zwischen Client und Server über Verbindungen mit hoher Latenzzeit zu minimieren. Plug-Ins führen entweder direkt im Anwendungsprozess oder in unmittelbarer Nähe aus, wenn sie von der Sandbox isoliert sind, so dass die Latenz selten ein Problem darstellt. Plug-in-Code sollte fokussierte Vorgänge sein, die schnell ausgeführt werden und die Blockade minimieren, um das Überschreiten von Timeout-Schwellen zu vermeiden und ein reaktionsfähiges System für synchrone Szenarien zu gewährleisten. Senden Sie jede Anforderung direkt, anstatt sie zu stapeln und als eine einzige Anforderung zu senden.

Beispiel: 'foreach (request in requests) service.Execute(request)'

Auf der Serverseite werden die in einer Batch-Anfrage enthaltenen Operationen sequentiell und nicht parallel ausgeführt. Dies ist auch dann der Fall, wenn die ExecuteMultipleSettings.ReturnResponses Eigenschaft wird auf false gesetzt. Entwickelnde neigen dazu, Batch-Anforderungen auf diese Weise zu verwenden, vorausgesetzt, sie ermöglichen eine parallele Verarbeitung. Batch-Anfragen werden dieses Ziel nicht erreichen.

Personen verwenden ExecuteTransactionRequest, um sicherzustellen, dass jeder Vorgang in einer Transaktion enthalten ist. Dies ist innerhalb eines synchronen Plug-In-Schritts unnötig, da das Plug-in oft bereits im Rahmen einer Datenbanktransaktion ausgeführt wird, wodurch die Notwendigkeit der Verwendung der ExecuteTransaction-Meldung entfällt.

Siehe auch

Ereignisframework
Laufzeitbeschränkungen
Mehrere Anforderungen mit dem SDK für .NET ausführen
Führt Nachrichten in einer einzelnen Datenbanktransaktion aus.

Hinweis

Können Sie uns Ihre Präferenzen für die Dokumentationssprache mitteilen? Nehmen Sie an einer kurzen Umfrage teil. (Beachten Sie, dass diese Umfrage auf Englisch ist.)

Die Umfrage dauert etwa sieben Minuten. Es werden keine personenbezogenen Daten erhoben. (Datenschutzbestimmungen).