Freigeben über


Problembehandlungs-Plug-Ins

Dieser Artikel enthält Informationen über Fehler, die bei der Ausführung von Plug-Ins auftreten können, und es zeigt, wie Sie diese beheben können.

Fehler: Sandbox-Worker-Prozess abgestürzt

Fehlercode: -2147204723
Fehlermeldung: The plug-in execution failed because the Sandbox Worker process crashed. This is typically due to an error in the plug-in code.

Dieser Fehler bedeutet einfach, dass der Arbeitsprozess, der Ihren Plug-in-Code ausführt, abgestürzt ist. Der Grund für den Absturz kann Ihr Plug-in sein, aber es könnte auch ein anderes Plug-in sein, das gleichzeitig für Ihr Unternehmen ausgeführt wird. Da der Prozess abgestürzt ist, können wir keine genaueren Informationen darüber gewinnen, warum er abgestürzt ist. Aber nach der nachträglichen Untersuchung von Daten aus den Crash-Dumps haben wir festgestellt, dass dies in der Regel aus einem der vier unten genannten Gründe geschieht:

  • Unbehandelte Ausnahme im Plugin
  • Stack Overflow-Fehler im Plugin
  • Verwendung von Threads, um Arbeit in eine Warteschlange zu stellen, ohne try/catch im Thread-Delegat
  • Worker-Prozess erreicht Speicherlimit

Unbehandelte Ausnahme im Plugin

Wie in Behandlung von Ausnahmen in Plug-ins erwähnt, sollten Sie beim Schreiben eines Plug-ins versuchen, vorauszusehen, welche Operationen fehlschlagen könnten, und diese in einen try-catch-Block verpacken. Wenn ein Fehler auftritt, sollten Sie die InvalidPluginExecutionException verwenden, um die Operation mit einem für den Benutzer aussagekräftigen Fehler elegant zu beenden.

Ein allgemeines Szenario hierfür ist die Verwendung der HttpClient.SendAsync-Methode oder HttpClient.GetAsync-Methode, die asynchrone Operationen sind, die eine Aufgabe zurückgeben. Damit dies in einem Plug-In funktioniert, in dem der Code synchron sein muss, können Benutzer die Aufgabe<TErgebnis>.Result-Eigenschaft verwenden. Wenn ein Fehler auftritt, gibt dies eine AggregateException zurück, die mehrere Fehler in einer einzigen Ausnahme zusammenfasst, was schwierig zu handhaben sein kann. Eher ist zu empfehlen, Task<TResult>.GetAwaiter().GetResult() zu verwenden, weil damit das Ergebnis als genau der Fehler weitergegeben wird, der die Störung hervorgerufen hat.

Das folgende Beispiel zeigt den korrekten Weg, die Ausnahme und einen ausgehenden Aufruf mit der HttpClient.GetAsync Methode zu verwalten. Dieses Plug-in versucht, den Antworttext für eine in der unsicheren Konfiguration festgelegte Url für einen dafür registrierten Schritt zu erhalten.

using Microsoft.Xrm.Sdk;
using System;
using System.Net.Http;

namespace ErrorRepro
{
    public class AsyncError : IPlugin
    {
        private readonly string webAddress;

        public AsyncError(string unsecureConfig)
        {
            if (string.IsNullOrEmpty(unsecureConfig)) {
                throw new InvalidPluginExecutionException("The ErrorRepro.AsyncError plug-in requires that a Url be set in the unsecure configuration for the step registration.");
            }
            webAddress = unsecureConfig;

        }

        public void Execute(IServiceProvider serviceProvider)
        {
            ITracingService tracingService =
            (ITracingService)serviceProvider.GetService(typeof(ITracingService));

            tracingService.Trace($"Starting ErrorRepro.AsyncError");
            tracingService.Trace($"Sending web request to {webAddress}");

            try
            {
                string responseText = GetWebResponse(webAddress, tracingService);
                tracingService.Trace($"Result: {responseText.Substring(0, 100)}");
            }
            catch (Exception ex)
            {
                tracingService.Trace($"Error: ErrorRepro.AsyncError {ex.Message}");
                throw new InvalidPluginExecutionException(ex.Message);
            }
            tracingService.Trace($"Ending ErrorRepro.AsyncError");
        }

        //Gets the text response of an outbound web service call
        public string GetWebResponse(string webAddress, ITracingService tracingService)
        {
            try
            {
                using (HttpClient client = new HttpClient())
                {
                    client.Timeout = TimeSpan.FromMilliseconds(15000); //15 seconds
                    client.DefaultRequestHeaders.ConnectionClose = true; //Set KeepAlive to false

                    HttpResponseMessage response = client.GetAsync(webAddress).GetAwaiter().GetResult(); //Make sure it is synchronous
                    response.EnsureSuccessStatusCode();

                    tracingService.Trace($"ErrorRepro.AsyncError.GetWebResponse succeeded.");

                    string responseContent = response.Content.ReadAsStringAsync().GetAwaiter().GetResult(); //Make sure it is synchronous

                    tracingService.Trace($"ErrorRepro.AsyncError.GetWebResponse responseContent parsed successfully.");

                    return responseContent;

                }
            }
            catch (Exception ex)
            {
                //Capture the inner exception message if it exists.
                // It should have a more specific detail.
                string innerExceptionMessage = string.Empty;
                if (ex.InnerException != null) {
                    innerExceptionMessage = ex.InnerException.Message;
                }

                tracingService.Trace($"Error in ErrorRepro.AsyncError : {ex.Message} InnerException: {innerExceptionMessage}");
                if (!string.IsNullOrEmpty(innerExceptionMessage))
                {
                    throw new Exception($"A call to an external web service failed. {innerExceptionMessage}", ex);
                }

                throw new Exception("A call to an external web service failed.", ex);
            }
        }
    }
}

Stack Overflow-Fehler im Plugin

Diese Art von Fehler tritt am häufigsten auf, direkt nachdem Sie eine Änderung in Ihrem Plug-in-Code vorgenommen haben. Manche Leute verwenden einen eigenen Satz von Basisklassen, um ihre Entwicklung zu rationalisieren. Manchmal entstehen diese Fehler durch Änderungen an diesen Basisklassen, von denen ein bestimmtes Plug-In abhängt.

Zum Beispiel kann ein rekursiver Aufruf ohne Abbruchbedingung oder eine Abbruchbedingung, die nicht alle Szenarien abdeckt, dazu führen, dass dies passiert. Weitere Informationen: StackOverflowException Klasse > Bemerkungen

Sie sollten alle Code-Änderungen überprüfen, die in letzter Zeit für das Plug-in und jeden anderen Code, von dem der Plug-in-Code abhängt, vorgenommen wurden.

Beispiel

Der folgende Plug-in-Code verursacht eine StackOverflowException aufgrund eines rekursiven Aufrufs ohne Grenzen. Trotz der Verwendung der Ablaufverfolgung und dem Versuch, den Fehler zu erfassen, wird weder die Ablaufverfolgung noch der Fehler zurückgegeben, da der worker-Prozess, der sie verarbeiten würde, beendet wurde.

using Microsoft.Xrm.Sdk;
using System;

namespace ErrorRepro
{
    public class SOError : IPlugin
    {
        public void Execute(IServiceProvider serviceProvider)
        {
            ITracingService tracingService =
           (ITracingService)serviceProvider.GetService(typeof(ITracingService));

            tracingService.Trace($"Starting ErrorRepro.SOError");

            try
            {
                tracingService.Trace($"Calling RecursiveMethodWithNoLimit to trigger StackOverflow error.");

                RecursiveMethodWithNoLimit(tracingService); //StackOverflowException occurs here.
            }
            catch (Exception ex)
            {
                //This trace will not be written
                tracingService.Trace($"Error in ErrorRepro.SOError {ex.Message}");

                //This error will never be thrown
                throw new InvalidPluginExecutionException($"Error in ErrorRepro.SOError. {ex.Message}");
            }

            //This trace will never be written
            tracingService.Trace($"Ending ErrorRepro.SOError");
        }

        public static void RecursiveMethodWithNoLimit(ITracingService tracingService)
        {
            tracingService.Trace($"Starting ErrorRepro.SOError.RecursiveMethodWithNoLimit");

            RecursiveMethodWithNoLimit(tracingService);

            tracingService.Trace($"Ending ErrorRepro.SOError.RecursiveMethodWithNoLimit");
        }
    }
}

Wenn der obige Plug-In-Code in einem synchronen Plug-In verwendet wird, wird der folgende Fehler von der Web-API zurückgegeben:

{
    "error": {
        "code": "0x8004418d",
        "message": "The plug-in execution failed because the Sandbox Worker process crashed. This is typically due to an error in the plug-in code.\r\nSystem.ServiceModel.CommunicationException: The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.\r\n   at Microsoft.Crm.Sandbox.SandboxWorkerProcess.Execute(SandboxCallInfo callInfo, SandboxPluginExecutionContext requestContext, Guid pluginAssemblyId, Int32 sourceHash, String assemblyName, Guid pluginTypeId, String pluginTypeName, String pluginConfiguration, String pluginSecureConfig, Boolean returnTraceInfo, Int64& wcfExecInMs, Int64& initializeInMs, Int64& trackCallInMs, Int64& trackGoodReturnInMs, Int64& waitInMs, Int64& taskStartDelay) +0x330: Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #8503641A",
        "@Microsoft.PowerApps.CDS.ErrorDetails.ApiExceptionSourceKey": "Plugin/ErrorRepro.SOError, ErrorRepro, Version=1.0.0.0, Culture=neutral, PublicKeyToken=c2bee3e550ec0851",
        "@Microsoft.PowerApps.CDS.ErrorDetails.ApiStepKey": "d5958631-b87e-eb11-a812-000d3a4f50a7",
        "@Microsoft.PowerApps.CDS.ErrorDetails.ApiDepthKey": "1",
        "@Microsoft.PowerApps.CDS.ErrorDetails.ApiActivityIdKey": "a3028bda-73c2-4eef-bcb5-157c5a4c323e",
        "@Microsoft.PowerApps.CDS.ErrorDetails.ApiPluginSolutionNameKey": "Active",
        "@Microsoft.PowerApps.CDS.ErrorDetails.ApiStepSolutionNameKey": "Active",
        "@Microsoft.PowerApps.CDS.ErrorDetails.ApiExceptionCategory": "SystemFailure",
        "@Microsoft.PowerApps.CDS.ErrorDetails.ApiExceptionMesageName": "SandboxWorkerNotAvailable",
        "@Microsoft.PowerApps.CDS.ErrorDetails.ApiExceptionHttpStatusCode": "500",
        "@Microsoft.PowerApps.CDS.HelpLink": "http://go.microsoft.com/fwlink/?LinkID=398563&error=Microsoft.Crm.CrmException%3a8004418d&client=platform",
        "@Microsoft.PowerApps.CDS.TraceText": "\r\n[ErrorRepro: ErrorRepro.SOError]\r\n[d5958631-b87e-eb11-a812-000d3a4f50a7: ErrorRepro.SOError: Create of account]\r\n\r\n",
        "@Microsoft.PowerApps.CDS.InnerError.Message": "The plug-in execution failed because the Sandbox Worker process crashed. This is typically due to an error in the plug-in code.\r\nSystem.ServiceModel.CommunicationException: The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.\r\n   at Microsoft.Crm.Sandbox.SandboxWorkerProcess.Execute(SandboxCallInfo callInfo, SandboxPluginExecutionContext requestContext, Guid pluginAssemblyId, Int32 sourceHash, String assemblyName, Guid pluginTypeId, String pluginTypeName, String pluginConfiguration, String pluginSecureConfig, Boolean returnTraceInfo, Int64& wcfExecInMs, Int64& initializeInMs, Int64& trackCallInMs, Int64& trackGoodReturnInMs, Int64& waitInMs, Int64& taskStartDelay) +0x330: Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #8503641A"
    }
}

So wird dieser Fehler im Plug-in-Trace-Protokoll aufgezeichnet:

Unhandled exception: 
Exception type: System.ServiceModel.FaultException`1[Microsoft.Xrm.Sdk.OrganizationServiceFault]
Message: The plug-in execution failed because the Sandbox Worker process crashed. This is typically due to an error in the plug-in code.
System.ServiceModel.CommunicationException: The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.
   at Microsoft.Crm.Sandbox.SandboxWorkerProcess.Execute(SandboxCallInfo callInfo, SandboxPluginExecutionContext requestContext, Guid pluginAssemblyId, Int32 sourceHash, String assemblyName, Guid pluginTypeId, String pluginTypeName, String pluginConfiguration, String pluginSecureConfig, Boolean returnTraceInfo, Int64& wcfExecInMs, Int64& initializeInMs, Int64& trackCallInMs, Int64& trackGoodReturnInMs, Int64& waitInMs, Int64& taskStartDelay) +0x330: Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #4BC22433Detail: 
<OrganizationServiceFault xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.microsoft.com/xrm/2011/Contracts">
  <ActivityId>48c5818e-4912-42f0-b1b6-e3bbe7ae013d</ActivityId>
  <ErrorCode>-2147204723</ErrorCode>
  <ErrorDetails xmlns:d2p1="http://schemas.datacontract.org/2004/07/System.Collections.Generic" />
  <HelpLink i:nil="true" />
  <Message>The plug-in execution failed because the Sandbox Worker process crashed. This is typically due to an error in the plug-in code.
System.ServiceModel.CommunicationException: The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.
   at Microsoft.Crm.Sandbox.SandboxWorkerProcess.Execute(SandboxCallInfo callInfo, SandboxPluginExecutionContext requestContext, Guid pluginAssemblyId, Int32 sourceHash, String assemblyName, Guid pluginTypeId, String pluginTypeName, String pluginConfiguration, String pluginSecureConfig, Boolean returnTraceInfo, Int64&amp; wcfExecInMs, Int64&amp; initializeInMs, Int64&amp; trackCallInMs, Int64&amp; trackGoodReturnInMs, Int64&amp; waitInMs, Int64&amp; taskStartDelay) +0x330: Microsoft Dynamics CRM has experienced an error. Reference number for administrators or support: #4BC22433</Message>
  <Timestamp>2021-03-06T22:14:22.0629638Z</Timestamp>
  <ExceptionRetriable>false</ExceptionRetriable>
  <ExceptionSource>WorkerCommunication</ExceptionSource>
  <InnerFault i:nil="true" />
  <OriginalException>System.ServiceModel.CommunicationException: The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.

Server stack trace: 
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]: 
   at Microsoft.Crm.Sandbox.SandboxWorkerProcess.Execute(SandboxCallInfo callInfo, SandboxPluginExecutionContext requestContext, Guid pluginAssemblyId, Int32 sourceHash, String assemblyName, Guid pluginTypeId, String pluginTypeName, String pluginConfiguration, String pluginSecureConfig, Boolean returnTraceInfo, Int64&amp; wcfExecInMs, Int64&amp; initializeInMs, Int64&amp; trackCallInMs, Int64&amp; trackGoodReturnInMs, Int64&amp; waitInMs, Int64&amp; taskStartDelay)</OriginalException>
  <TraceText i:nil="true" />
</OrganizationServiceFault>

Verwendung von Threads, um Arbeit in eine Warteschlange zu stellen, ohne try/catch im Thread-Delegat

Sie sollten keine parallelen Ausführungsmuster in Plug-Ins verwenden. Dies wird in diesem Artikel über bewährte Verfahren gefordert: Verwenden Sie keine parallele Ausführung in Plug-Ins und Workflowaktivitäten. Die Verwendung dieser Muster kann zu Problemen bei der Verwaltung der Transaktion in einem synchronen Plug-In führen. Ein weiterer Grund, diese Muster nicht zu verwenden, ist jedoch, dass jede Arbeit, die außerhalb eines try/catch-Blocks in einem Thread-Delegat ausgeführt wird, den worker-Prozess zum Absturz bringen kann.

Worker-Prozess erreicht Speicherlimit

Jeder worker-Prozess verfügt über eine endliche Menge an Speicher. Es gibt Bedingungen, unter denen mehrere gleichzeitige Operationen, die große Datenmengen beinhalten, den verfügbaren Speicher überschreiten und den Arbeitsprozess zum Absturz bringen können.

RetrieveMultiple mit Dateidaten

Das allgemeine Szenario in diesem Fall ist, dass ein Plug-In für eine RetrieveMultiple-Operation ausgeführt wird, bei der die Anfrage Dateidaten enthält. Zum Beispiel beim Abrufen von E-Mails, die irgendwelche Dateianhänge enthalten. Die Datenmenge, die in einer solchen Abfrage zurückgegeben werden kann, ist nicht vorhersehbar, da jede E-Mail mit einer beliebigen Anzahl von Dateianhängen verbunden sein kann und die Anhänge selbst unterschiedlich groß sein können.

Wenn mehrere Anfragen ähnlicher Art gleichzeitig ausgeführt werden, wird der benötigte Speicherplatz groß. Wenn er das Limit überschreitet, stürzt der Prozess ab. Der Schlüssel, um dies zu verhindern, ist die Begrenzung von RetrieveMultiple-Abfragen, die Entitäten mit zugehörigen Dateianhängen enthalten. Rufen Sie die Datensätze mit RetrieveMultiple ab, aber rufen Sie bei Bedarf alle zugehörigen Dateien mit einzelnen Retrieve-Operationen ab.

Speicherlecks

Ein weniger allgemeines Szenario ist, dass der Code des Plug-Ins Speicherlecks aufweist. Dies kann vorkommen, wenn das Plug-In nicht zustandslos geschrieben ist, was ein weiteres bewährtes Verfahren ist: Entwickeln Sie IPlugin-Implementierungen als zustandslos. Wenn das Plug-In nicht zustandslos ist und versucht wird, kontinuierlich Daten zu einer zustandsabhängigen Eigenschaft wie einem Array hinzuzufügen. Die Datenmenge wächst bis zu dem Punkt, an dem sie den gesamten verfügbaren Speicher verbraucht.

Transaktionsfehler

Es gibt zwei häufige Arten von Fehlern im Zusammenhang mit Transaktionen:

Fehlercode: -2146893812
Fehlermeldung: ISV code reduced the open transaction count. Custom plug-ins should not catch exceptions from OrganizationService calls and continue processing.

Fehlercode: -2147220911
Fehlermeldung: There is no active transaction. This error is usually caused by custom plug-ins that ignore errors from service calls and continue processing.

Hinweis

Der oberste Fehler wurde zuletzt hinzugefügt. Sie sollte sofort und im Zusammenhang mit dem Plugin, das das Problem enthält, auftreten. Der untere Fehler kann immer noch unter verschiedenen Umständen auftreten, typischerweise mit benutzerdefinierten Workflow-Aktivitäten. Es kann an Problemen in einem anderen Plugin liegen.

Um die Nachricht zu verstehen, müssen Sie bedenken, dass bei einem Fehler des Datenvorgangs im synchronen Plug-In jedes Mal die Transaktion für den gesamten Vorgang beendet wird.

Mehr Informationen: Skalierbares Anpassungsdesign in Microsoft Dataverse

Die häufigste Ursache ist einfach, dass ein Entwickler glaubt, er könne versuchen, eine Operation auszuführen, die möglicherweise erfolgreich ist und er diese Operation in einem try/catch-Block verpackt und versucht, den Fehler zu schlucken, wenn die Operation fehlschlägt.

Auch wenn dies bei einer Clientanwendung funktionieren kann, bei der Ausführung eines Plug-Ins führt jeder Datenvorgangsfehler zum Rollback der gesamte Transaktion. Sie können die Fehler nicht schlucken, daher müssen Sie sicherstellen, stets InvalidPluginExecutionException zurückzugeben.

Fehler: SQL-Fehler: Ausführungs-Timeout abgelaufen

Fehlercode: -2147204783
Fehlermeldung: Sql error: 'Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding.'

Es gibt viele Gründe für einen SQL-Timeout-Fehler.

Blockierung

Blockierung ist die häufigste Ursache für einen SQL-Timeout-Fehler, da der Vorgang auf Ressourcen wartet, die von einer anderen SQL-Transaktion gesperrt sind. Dieser Fehler entsteht, wenn das System die Integrität der Daten schützt und bei über lange Zeit ausgeführten Anforderungen, die sich auf die Leistung für Benutzer auswirken.

Blockierung kann durch andere gleichzeitige Operationen verursacht werden. Ihr Code funktioniert ggf. gut in einer isolierten Testumgebung und kann dennoch für Bedingungen anfällig sein, die nur auftreten, wenn mehrere Benutzer die Logik im Plug-In initiieren.

Beim Schreiben von Plug-Ins ist es wichtig, nachvollziehen zu können, wie skalierbare Anpassungen entwickelt werden. Weitere Informationen: Skalierbares Anpassungsdesign in Dataverse

Weitergabevorgänge

Bestimmte Aktionen, die Sie in Ihrem Plug-In vornehmen, z. B: das Zuweisen oder Löschen eines Datensatzes, kann einzelne Vorgänge in verknüpften Datensätzen initiieren. Diese Aktionen können Sperren auf den verknüpften Datensätzen anwenden, die verursachen, dass nachfolgende Datenvorgänge blockiert werden, was wiederum zu einem SQL-Timeout führen kann.

Sie sollten die möglichen Auswirkungen dieser überlappenden Vorgänge auf Datenvorgänge in Ihrem Plug-In bedenken. Weitere Informationen: Verhalten von Tabellenbeziehungen

Da dieses Verhalten zwischen Umgebungen unterschiedlich konfiguriert werden kann, ist das Verhalten möglicherweise schwer reproduzierbar, außer die Umgebungen werden gleich konfiguriert.

Indizes auf neuen Tabellen

Wenn das Plug-in Operationen mit einer Tabelle oder einer Spalte durchführt, die erst kürzlich erstellt wurde, können einige Funktionalitäten von Azure SQL zur Verwaltung von Indizes nach ein paar Tagen einen Unterschied machen.

Fehler aufgrund von Benutzerrechten

In einer Clientanwendung können Sie Befehle deaktivieren, die Benutzer nicht ausführen dürfen. In einem Plug-Ins ist dies nicht vorhanden. Ihr Code enthält ggf. einige Automatisierungen, für deren Ausführung der aufrufende Benutzer keine Rechte hat ist.

Sie können registrieren, dass das Plug-In im Rahmen eines Benutzers ausgeführt wird, der die richtigen Rechte hat, indem Sie den Wert Ausführung im Kontext des Benutzers für den Benutzer festlegen. Oder Sie können den Vorgang ausführen, indem Sie die Identität einen anderen Benutzers annehmen. Weitere Informationen:

Fehler: Nachrichtengröße beim Senden von Kontext an den Sandkasten überschritten

Fehlercode: -2147220970
Fehlermeldung: Message size exceeded when sending context to Sandbox. Message size: ### Mb

Dieser Fehler tritt auf, wenn eine Message-Nutzlast größer als 116,85 MB ist UND ein Plug-In für die Message registriert ist. Die Fehlermeldung enthält die Größe der Nutzlast, die den Fehler verursacht hat.

Die Beschränkung stellt sicher, dass Benutzer, die Anwendungen ausführen, sich nicht aufgrund vorhandener Ressourceneinschränkungen gegenseitig stören. Die Einschränkung bietet einen gewissen Schutz vor ungewöhnlich großen Message-Nutzlasten, die die Verfügbarkeit und Leistungsfähigkeit der Dataverse-Plattform gefährdet.

116,85 MB ist groß genug, dass dieser Fall eher selten eintreten sollte. Die wahrscheinlichste Situation, in der dieser Fall eintreten könnte, ist, wenn Sie einen Datensatz mit mehreren Datensätzen abrufen, die große Binärdateien enthalten.

Wenn dieser Fehler auftritt, können Sie:

  1. Das Plug-In für die Message entfernen Wenn es keine Plug-Ins gibt, die für die Message registriert, wird der Vorgang ohne ein Fehler abgeschlossen.
  2. Wenn der Fehler in einem benutzerdefinierten Client auftritt, können Sie Ihren Code ändern, damit er nicht versucht, die Aufgabe in einem einzelnen Vorgang auszuführen. Schreiben Sie stattdessen Code, um die Daten in kleineren Teilen abzurufen.

Fehler: Der entsprechende Schlüssel war nicht im Wörterbuch vorhanden

Dataverse verwendet häufig Klassen, die von der abstrakten DataCollection<TKey,TValue>-Klasse abgeleitet wurden, die eine Sammlung von Schlüsseln und Werten darstellt. Beispiel: Mit Plug-Ins ist die Eigenschaft IExecutionContext.InputParameters eine ParameterCollection, die von der DataCollection<TKey,TValue>-Klasse abgeleitet wurde. Diese Klassen sind im Wesentlichen Wörterbuchobjekte, bei denen Sie mithilfe des Schlüsselnamens auf einen bestimmten Wert zugreifen.

Fehlercodes

Dieser Fehler tritt auf, wenn der Schlüsselwert im Code nicht in der Sammlung ist. Dies ist eher ein Laufzeitfehler als ein Plattformfehler. Wenn dieser Fehler innerhalb eines in Plug-Ins auftritt, hängt der Fehlercode davon ab, ob der Fehler entdeckt wurde.

Wenn der Entwickler die Ausnahme entdeckt hat und eine InvalidPluginExecutionException zurückgegeben hat, wie unter Behandlung von Ausnahmen in Plug-Ins beschrieben, wird der folgende Fehler zurückgegeben:

Fehlercode: -2147220891
Fehlermeldung: ISV code aborted the operation.

Bei diesem Fehler passiert es jedoch häufig, dass der Entwickler ihn nicht richtig entdeckt, und dann wird der folgende Fehler zurückgegeben:

Fehlercode: -2147220956
Fehlermeldung: An unexpected error occurred from ISV code.

Hinweis

„ISV” steht für Unabhängige Softwarehersteller (Independent Software Vendor).

Ursachen

Dieser Fehler tritt auf häufig zur Entwurfszeit auf und kann aufgrund eines Schreibfehlers oder durch Verwendung der falschen Groß-/Kleinschreibung auftreten. Bei Schlüsselwerten ist auf die Groß-/Kleinschreibung zu achten.

Während der Laufzeit tritt der Fehler häufig auf, weil der Entwickler davon ausgeht, dass der Wert vorhanden ist, aber dies nicht der Fall ist. Zum Beispiel werden in einem Plug-in, das für die Aktualisierung einer Tabelle registriert ist, nur die Werte, die geändert werden, in den Entity.Attributes aufgenommen Sammlung

Vorbeugung

Um diesen Fehler zu verhindern, müssen Sie überprüfen, dass der Schlüssel auch vorhanden ist, bevor Sie versuchen, ihn zu verwenden, um auf einen Wert zuzugreifen.

Wenn Sie zum Beispiel auf eine Spalte einer Tabelle zugreifen, können Sie mit der Entity.Contains(String) Methode verwenden, um zu prüfen, ob eine Spalte in einer Tabelle existiert, wie im folgenden Code gezeigt.

// Obtain the execution context from the service provider.  
IPluginExecutionContext context = (IPluginExecutionContext)
    serviceProvider.GetService(typeof(IPluginExecutionContext));

// The InputParameters collection contains all the data passed in the message request.  
if (context.InputParameters.Contains("Target") &&
    context.InputParameters["Target"] is Entity)
    {
    // Obtain the target entity from the input parameters.  
    Entity entity = (Entity)context.InputParameters["Target"];

    //Check whether the name attribute exists.
    if(entity.Contains("name"))
    {
        string name = entity["name"];
    }

Einige Entwickler verwenden die Methode Entity.GetAttributeValue<T>(String) Methode verwenden, um diesen Fehler beim Zugriff auf eine Tabellenspalte zu vermeiden, aber beachten Sie, dass diese Methode den Standardwert des Typs zurückgibt, wenn die Spalte nicht existiert. Wenn der Standardwert Null ist, funktioniert dies wie erwartet. Wenn jedoch der Standardwert nicht Null zurückgibt, beispielsweise bei DateTime, wird eher der Wert 1/1/0001 00:00 als Null zurückgegeben.

Fehler: Sie können keine Transaktion mit einem anderen Isolationslevel starten, als bereits für die aktuelle Transaktion festgelegt ist

Fehlercode: -2147220989
Fehlermeldung: You cannot start a transaction with a different isolation level than is already set on the current transaction

Plug-ins sind dazu gedacht, Geschäftslogik zu unterstützen. Das Ändern eines Teils des Datenschemas innerhalb des synchronen Plug-ins wird nicht unterstützt. Diese Vorgänge dauern häufig länger und können dazu führen, dass von Anwendungen verwendete Zwischenspeicher-Metadaten nicht mehr synchronisiert werden. Diese Operationen können jedoch in einem Plugin-Schritt ausgeführt werden, der zum asynchronen Ausführen registriert ist.

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).