Freigeben über


Problembehandlung für Dataverse-Plug-Ins

Dieser Artikel enthält Informationen zu Fehlern, die während der Plug-In-Ausführung auftreten können, oder zu Dataverse-Fehlern, die sich auf Plug-Ins beziehen, und zu deren Vermeidung oder Behebung.

Fehler "Zeitkonvertierung konnte nicht abgeschlossen werden"

Fehlercode: -2147220956
Fehlermeldung: Die Konvertierung konnte nicht abgeschlossen werden, da für die angegebene DataTime die Kind-Eigenschaft nicht ordnungsgemäß festgelegt wurde. Wenn die Kind-Eigenschaft beispielsweise DateTimeKind.Local ist, muss die Quellzeitzone TimeZoneInfo.Local sein.

Dieser Fehler kann während eines Aufrufs TimeZoneInfo.ConvertTimeToUtc(DateTime, TimeZoneInfo) im Plug-In-Code auftreten, um einen DateTime Wert in der Zeitzone Santiago oder Volgograd in koordinierte Weltzeit (UTC) zu konvertieren.

Dieser Fehler wird durch eine bekannte Produkteinschränkung verursacht, und es gibt derzeit keine Problemumgehung.

Weitere Informationen finden Sie unter Angeben von Zeitzoneneinstellungen für einen Benutzer.

Fehler "Sandbox-Workerprozess abgestürzt"

Fehlercode: -2147204723
Fehlermeldung: Fehler bei der Plug-In-Ausführung, weil der Sandbox-Workerprozess abgestürzt ist. Dies ist in der Regel auf einen Fehler im Plug-In-Code zurückzuführen.

Dieser Fehler bedeutet einfach, dass der Arbeitsprozess, bei dem Ihr Plug-In-Code ausgeführt wird, abgestürzt ist. Ihr Plug-In kann der Grund für den Absturz sein, aber es kann auch ein weiteres Plug-In sein, das gleichzeitig für Ihre organization ausgeführt wird. Da der Prozess abgestürzt ist, können wir keine spezifischeren Informationen darüber extrahieren, warum er abstürzt. Nach der Untersuchung der Daten aus den Absturzabbildern nach der Tatsache haben wir jedoch festgestellt, dass dieser Fehler in der Regel aus einem der vier Gründe auftritt:

Ausnahme ohne Behandlung im Plug-In

Wenn Sie ein Plug-In schreiben, sollten Sie versuchen, vorherzusagen, welche Vorgänge möglicherweise fehlschlagen, und sie in einem try-catch-Block umschließen. Wenn ein Fehler auftritt, sollten Sie die InvalidPluginExecutionException -Klasse verwenden, um den Vorgang ordnungsgemäß mit einem für den Benutzer aussagekräftigen Fehler zu beenden.

Weitere Informationen finden Sie unter Behandeln von Ausnahmen in Plug-Ins.

Ein häufiges Szenario für diese Ausnahme ist die Verwendung der HttpClient.SendAsync- oder HttpClient.GetAsync-Methode . Diese HttpClient-Methoden sind asynchrone Vorgänge, die einen Task zurückgeben. Um in einem Plug-In zu arbeiten, in dem Code synchron sein muss, können Benutzer das Task-TResult<> verwenden. Result-Eigenschaft. Wenn ein Fehler auftritt, Result gibt eine AggregateException zurück. Ein AggregateException konsolidiert mehrere Fehler in einer einzigen Ausnahme, die schwierig zu behandeln sein kann. Ein besserer Entwurf ist die Verwendung von Task<TResult>. GetAwaiter(). GetResult(), da die Ergebnisse als der spezifische Fehler weitergegeben werden, der den Fehler verursacht hat.

Das folgende Beispiel zeigt die richtige Methode zum Verwalten der Ausnahme und eines ausgehenden Aufrufs mithilfe der HttpClient.GetAsync-Methode . Dieses Plug-In versucht, den Antworttext für einen URI abzurufen, der in der unsicheren Konfiguration für einen dafür registrierten Schritt festgelegt wurde.

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);
            }
        }
    }
}

Verwenden von Threads zur Warteschlange ohne try/catch im Threaddelegat

Sie sollten keine parallelen Ausführungsmuster in Plug-Ins verwenden. Dieses Antimuster wird im Artikel zu bewährten Methoden hervorgehoben: Verwenden Sie keine parallele Ausführung innerhalb von Plug-Ins und Workflowaktivitäten. Die Verwendung dieser Muster kann probleme beim Verwalten der Transaktion in einem synchronen Plug-In verursachen. Ein weiterer Grund, diese Muster nicht zu verwenden, ist jedoch, dass jede Arbeit, die außerhalb eines try/catch Blocks in einem Threaddelegat ausgeführt wird, den Arbeitsprozess abstürzen kann.

Wichtig

Wenn der Arbeitsprozess abstürzt, wird die Ausführung Ihres Plug-Ins und anderer Plug-Ins, die derzeit in diesem Prozess ausgeführt werden, beendet. Dies schließt Plug-Ins ein, die Sie nicht besitzen oder verwalten.

Application Insights zur Rettung

In der Vergangenheit war das Abrufen der Stapelablaufverfolgung oder anderer Ausführungsinformationen für nicht behandelte Plug-In-Ausnahmen vom abgestürzten Arbeitsprozess nicht möglich. Dataverse bietet jetzt jedoch Unterstützung für die Protokollierung von Ausführungsfehlern in Application Insights. Um diese Funktion zu aktivieren, können Sie Application Insights mit der Umgebung verknüpfen, in der Ihr Plug-In registriert ist. Nach der Verknüpfung erfolgt die Protokollierung von Plug-In-Abstürze automatisch.

Weitere Informationen finden Sie unter Exportieren von Daten in Application Insights.

Nachdem eine Application Insights-Umgebung verknüpft wurde, stehen die folgenden Daten eines Arbeitsprozessabsturzes zur Problembehandlung zur Verfügung.

Beispiel für einen Absturzbericht des Application Insights-Plug-Ins.

Führen Sie die folgenden Schritte aus, um zum Absturzbericht in Application Insights zu navigieren:

  1. Verknüpfen Sie Application Insights mit Ihrer Umgebung.
  2. Warten Sie, bis eine Plug-In-Ausnahme zum Absturzfehler des Arbeitsprozesses führt.
  3. Navigieren Sie im Power Platform Admin Center zu Application Insights.
  4. Wählen Sie auf der Seite Application Insights im linken Bereich Fehler aus.
  5. Wählen Sie auf der Seite Fehler die Option Ausnahmen aus.
  6. Wählen Sie unter Ausnahmeproblem-ID in der Liste Gesamt die Option Microsoft.PowerPlatform.Dataverse.Plugin.PluginWorkerCrashException aus.
  7. Wählen Sie auf der rechten Seite unter Gesamt die Option PluginWorkerCrashException aus. Nun werden die Details aller aufgezeichneten Ausnahmen für Den Absturz des Arbeitsprozesses angezeigt.
  8. Search für aus, und wählen Sie die gewünschte Ausnahme im linken Bereich aus, und der Ausnahmedetailsbericht wird auf der rechten Seite der Seite angezeigt (ein Beispiel finden Sie im vorherigen Screenshot).
  9. Erweitern Sie crashDetails im Bericht, um auf die Stapelüberwachung zuzugreifen.

Stapelüberlauffehler im Plug-In

Diese Art von Fehler tritt am häufigsten direkt auf, nachdem Sie einige Änderungen am Plug-In-Code vorgenommen haben. Einige Benutzer verwenden ihre eigenen Basisklassen, um ihre Entwicklungserfahrung zu optimieren. Manchmal stammen diese Fehler aus Änderungen an den Basisklassen, von denen ein bestimmtes Plug-In abhängt.

Beispielsweise kann ein rekursiver Aufruf ohne Beendigungsbedingung oder eine Beendigungsbedingung, die nicht alle Szenarien abdeckt, dazu führen, dass dieser Fehler auftritt. Weitere Informationen finden Sie unter Hinweise zur StackOverflowException-Klasse>.

Sie sollten alle Codeänderungen überprüfen, die kürzlich für das Plug-In angewendet wurden, sowie alle anderen Code, von denen der Plug-In-Code abhängt.

Beispiel

Der folgende Plug-In-Code verursacht einen StackOverflowException aufgrund eines rekursiven Aufrufs ohne Einschränkungen. Trotz der Verwendung der Ablaufverfolgung und dem Versuch, den Fehler zu erfassen, werden die Ablaufverfolgung und der Fehler nicht zurückgegeben, da der Arbeitsprozess, 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");
        }
    }
}

In einem synchronen Plug-In-Schritt gibt der zuvor gezeigte Plug-In-Code den folgenden Fehler in der Web-API zurück, wenn die Anforderung so konfiguriert ist, dass sie zusätzliche Details mit Fehlern enthält.

{
    "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"
    }
}

Im Folgenden wird gezeigt, wie dieser Fehler im Tracelog des Plug-Ins aufgezeichnet wird:

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>

Der Arbeitsprozess erreicht das Arbeitsspeicherlimit

Jeder Arbeitsprozess verfügt über eine begrenzte Menge an Arbeitsspeicher. Es gibt Bedingungen, unter denen mehrere gleichzeitige Vorgänge, die große Datenmengen enthalten, den verfügbaren Arbeitsspeicher überschreiten und dazu führen können, dass der Prozessworker abstürzt.

RetrieveMultiple with File data

Das häufige Szenario ist in diesem Fall, wenn ein Plug-In für einen RetrieveMultiple Vorgang ausgeführt wird, bei dem die Anforderung Dateidaten enthält. Beispielsweise beim Abrufen von E-Mails, die Dateianlagen enthalten. Die Menge der Daten, die in einer Abfrage wie dieser zurückgegeben werden kann, ist unvorhersehbar, da jede E-Mail möglicherweise mit einer beliebigen Anzahl von Dateianlagen zusammenhängt und die Anlagen in ihrer Größe variieren können.

Wenn mehrere anforderungen ähnlicher Art gleichzeitig ausgeführt werden, wird die erforderliche Arbeitsspeichermenge groß. Wenn die Arbeitsspeichermenge den Grenzwert überschreitet, stürzt der Prozess ab. Der Schlüssel zum Verhindern dieser Situation ist das Einschränken von RetrieveMultiple Abfragen, die Entitäten mit verknüpften Dateianlagen enthalten. Rufen Sie die Datensätze mit RetrieveMultipleab, aber rufen Sie alle zugehörigen Dateien nach Bedarf mithilfe einzelner Retrieve Vorgänge ab.

Speicherverluste

Ein weniger häufiges Szenario ist, dass der Code im Plug-In Arbeitsspeicher verloren geht. Diese Situation kann auftreten, wenn das Plug-In nicht als zustandslos geschrieben wird. Dies ist eine weitere bewährte Methode. Weitere Informationen finden Sie unter Entwickeln von Plug-In-Implementierungen als zustandslos. Wenn das Plug-In nicht zustandslos ist und versucht wird, einer zustandsbehafteten Eigenschaft wie einem Array kontinuierlich Daten hinzuzufügen, wächst die Datenmenge bis zu dem Punkt, an dem der gesamte verfügbare Arbeitsspeicher verwendet wird.

Transaktionsfehler

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

Fehlercode: -2146893812
Fehlermeldung: ISV-Code hat die Anzahl geöffneter Transaktionen reduziert. Benutzerdefinierte Plug-Ins sollten keine Ausnahmen von OrganizationService-Aufrufen abfangen und die Verarbeitung fortsetzen.

Fehlercode: -2147220911
Fehlermeldung: Es ist keine aktive Transaktion vorhanden. Dieser Fehler wird in der Regel durch benutzerdefinierte Plug-Ins verursacht, die Fehler von Dienstaufrufen ignorieren und die Verarbeitung fortsetzen.

Hinweis

Der häufigste Fehler wurde zuletzt hinzugefügt. Sie sollte sofort und im Kontext des Plug-Ins auftreten, das das Problem enthält. Der untere Fehler kann unter verschiedenen Umständen auftreten, in der Regel benutzerdefinierte Workflowaktivitäten. Dies kann auf Probleme in einem anderen Plug-In zurückzuführen sein.

Jedes Mal, wenn ein Fehler im Zusammenhang mit einem Datenvorgang innerhalb eines synchronen Plug-Ins auftritt, wird die Transaktion für den gesamten Vorgang beendet.

Weitere Informationen finden Sie unter Skalierbares Anpassungsdesign in Microsoft Dataverse.

Eine häufige Ursache ist, dass ein Entwickler glaubt, dass er versuchen kann, einen Vorgang auszuführen, der möglicherweise erfolgreich ist, sodass er diesen Vorgang in einem try/catch -Block umschließt und versucht, den Fehler zu schlucken, wenn er fehlschlägt.

Dieses Muster kann zwar für eine Clientanwendung funktionieren, aber bei der Ausführung eines Plug-Ins führt jeder Fehler beim Datenvorgang zum Rollback der gesamten Transaktion. Sie können den Fehler nicht schlucken, daher müssen Sie sicherstellen, dass immer ein InvalidPluginExecutionExceptionzurückgegeben wird.

Fehler "SQL-Fehler: Ausführungstimeout abgelaufen"

Fehlercode: -2147204783
Fehlermeldung: SQL-Fehler: "Ausführungstimeout abgelaufen. Der Timeoutzeitraum, der vor Abschluss des Vorgangs verstrichen ist, oder der Server reagiert nicht."

Ursache

Es gibt eine Vielzahl von Gründen, warum ein SQL-Timeoutfehler auftreten kann. Drei davon werden hier beschrieben:

Blockieren

Die häufigste Ursache für einen SQL-Timeoutfehler ist, dass der Vorgang auf Ressourcen wartet, die von einer anderen SQL-Transaktion blockiert wurden. Der Fehler ist darauf zurückzuführen, dass Dataverse die Integrität der Daten schützt und vor anforderungen mit langer Ausführungsdauer, die sich auf die Leistung für Benutzer auswirken.

Die Blockierung kann auf andere gleichzeitige Vorgänge zurückzuführen sein. Ihr Code funktioniert möglicherweise isoliert in einer Testumgebung und ist dennoch anfällig für Bedingungen, die nur auftreten, wenn mehrere Benutzer die Logik in Ihrem Plug-In initiieren.

Beim Schreiben von Plug-Ins ist es wichtig zu verstehen, wie skalierbare Anpassungen entworfen werden können. Weitere Informationen finden Sie unter Skalierbares Anpassungsdesign in Dataverse.

Kaskadierende Vorgänge

Bestimmte Aktionen, die Sie in Ihrem Plug-In vornehmen, z. B. das Zuweisen oder Löschen eines Datensatzes, können kaskadierende Vorgänge für verwandte Datensätze initiieren. Diese Aktionen können Sperren für verwandte Datensätze anwenden, was dazu führt, dass nachfolgende Datenvorgänge blockiert werden, was wiederum zu einem SQL-Timeout führen kann.

Sie sollten die möglichen Auswirkungen dieser kaskadierenden Vorgänge auf Datenvorgänge in Ihrem Plug-In berücksichtigen. Weitere Informationen finden Sie unter Verhalten von Tabellenbeziehungen.

Da diese Verhaltensweisen zwischen Umgebungen unterschiedlich konfiguriert werden können, ist das Verhalten möglicherweise schwierig zu reproduzieren, es sei denn, die Umgebungen sind auf die gleiche Weise konfiguriert.

Indizes für neue Tabellen

Wenn das Plug-In Vorgänge mit einer Tabelle oder Spalte ausführt, die kürzlich erstellt wurde, können einige Azure SQL Funktionen zum Verwalten von Indizes nach einigen Tagen einen Unterschied machen.

Fehler aufgrund von Benutzerberechtigungen

In einer Clientanwendung können Sie Befehle deaktivieren, die Benutzer nicht ausführen dürfen. Innerhalb eines Plug-Ins haben Sie diese Möglichkeit nicht. Ihr Code kann einige Automatisierungen enthalten, die der aufrufende Benutzer nicht über die Erforderlichen verfügt.

Sie können das Plug-In registrieren, um es im Kontext eines Benutzers auszuführen, von dem bekannt ist, dass er über die richtigen Berechtigungen verfügt, indem Sie den Wert In Benutzerkontext ausführen auf diesen Benutzer festlegen. Alternativ können Sie den Vorgang ausführen, indem Sie die Identität eines anderen Benutzers annehmen. Weitere Informationen finden Sie unter:

Fehler beim Ausführen im Kontext eines deaktivierten Benutzers

Wenn ein Plug-In im Kontext eines deaktivierten Benutzers ausgeführt wird, wird der folgende Fehler zurückgegeben:

Fehlermeldung: System.ServiceModel.FaultException'1[Microsoft.Xrm.Sdk.OrganizationServiceFault]: Der Benutzer mit SystemUserId=<User-ID> in OrganizationContext=<Context> ist deaktiviert. Deaktivierte Benutzer können nicht auf das System zugreifen. Erwägen Sie, diesen Benutzer zu aktivieren. Außerdem sind Benutzer deaktiviert, wenn ihnen keine Lizenz zugewiesen ist.

Um diesen Fehler zu beheben, können Sie eine Abfrage ausführen, um die für den deaktivierten Benutzer registrierten Schritte sowie das zugehörige Plug-In und SdkMessage Details zu ermitteln.

https://<env-url>/api/data/v9.2/sdkmessageprocessingsteps
?$filter=_impersonatinguserid_value eq '<disabled-userId-from-error>'&
$expand=plugintypeid($select=name,friendlyname,assemblyname;
$expand=pluginassemblyid($select=solutionid,name,isolationmode)),sdkmessageid($select=solutionid,name)&
$select=solutionid,name,stage,_impersonatinguserid_value,mode

Fehler "Meldungsgröße beim Senden von Kontext an Sandbox überschritten"

Fehlercode: -2147220970
Fehlermeldung: Die Nachrichtengröße wurde beim Senden des Kontexts an die Sandbox überschritten. Nachrichtengröße: ### Mb

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

Der Grenzwert trägt dazu bei, dass Benutzer, die Anwendungen ausführen, sich basierend auf Ressourceneinschränkungen nicht gegenseitig stören können. Der Grenzwert bietet einen Schutz vor ungewöhnlich großen Nachrichtennutzlasten, die die Verfügbarkeit und Leistungsmerkmale der Dataverse-Plattform gefährden.

116,85 MB sind groß genug, dass dieser Fall selten auftreten sollte. Die wahrscheinlichste Situation, in der dieser Fall auftreten kann, ist das Abrufen eines Datensatzes mit mehreren verwandten Datensätzen, die große Binärdateien enthalten.

Wenn sie diesen Fehler erhalten, haben Sie folgende Möglichkeiten:

  1. Entfernen Sie das Plug-In für die Nachricht. Wenn keine Plug-Ins für die Nachricht registriert sind, wird der Vorgang ohne Fehler abgeschlossen.
  2. Wenn der Fehler in einem benutzerdefinierten Client auftritt, können Sie Den Code so ändern, dass er nicht versucht, die Arbeit in einem einzigen Vorgang auszuführen. Schreiben Sie stattdessen Code, um die Daten in kleineren Teilen abzurufen.

Fehler "Der angegebene Schlüssel war nicht im Wörterbuch vorhanden"

Dataverse verwendet häufig Klassen, die von der abstrakten DataCollection<TKey,TValue> Klasse abgeleitet sind, die eine Auflistung von Schlüsseln und Werten darstellt. Bei Plug-Ins ist z. B. die IExecutionContextEigenschaft .InputParameters eine ParameterCollection von der DataCollection<TKey,TValue> -Klasse abgeleitete . 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 Auflistung vorhanden ist. Das Ergebnis ist ein Laufzeitfehler anstelle eines Plattformfehlers. Wenn dieser Fehler innerhalb eines Plug-Ins auftritt, hängt der Fehlercode davon ab, ob der Fehler abgefangen wurde.

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

Fehlercode: -2147220891
Fehlermeldung: DER ISV-Code hat den Vorgang abgebrochen.

Bei diesem Fehler ist es jedoch üblich, dass der Entwickler ihn nicht ordnungsgemäß abfängt, und der folgende Fehler wird zurückgegeben:

Fehlercode: -2147220956
Fehlermeldung: Unerwarteter Fehler im ISV-Code.

Hinweis

"ISV" steht für Independent Software Vendor.

Ursache

Dieser Fehler tritt häufig zur Entwurfszeit auf und kann auf einen Rechtschreibfehler oder die Verwendung der falschen Groß-/Kleinschreibung zurückzuführen sein. Bei den Schlüsselwerten wird die Groß-/Kleinschreibung beachtet.

Zur Laufzeit ist der Fehler häufig darauf zurückzuführen, dass der Entwickler davon ausgeht, dass der Wert vorhanden ist, wenn er nicht vorhanden ist. In einem Plug-In, das für die Aktualisierung einer Tabelle registriert ist, sind beispielsweise nur die Werte, die geändert wurden, in der EntityAuflistungAttributes enthalten.

Fehlerbehebung

Um diesen Fehler zu beheben, müssen Sie überprüfen, ob der Schlüssel vorhanden ist, bevor Sie versuchen, ihn für den Zugriff auf einen Wert zu verwenden.

Wenn Sie beispielsweise auf eine Tabellenspalte zugreifen, können Sie die EntityMethode verwendenContains(String) , um zu überprüfen, ob eine Spalte in einer Tabelle vorhanden ist, 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 Entity.GetAttributeValue<T>(String) -Methode, um diesen Fehler beim Zugriff auf eine Tabellenspalte zu vermeiden. Diese Methode gibt den Standardwert des Typs zurück, wenn die Spalte nicht vorhanden ist. Wenn der Standardwert NULL ist, funktioniert diese Methode wie erwartet. Wenn der Standardwert jedoch nicht NULL zurückgibt, z. B. bei einem DateTime, ist 1/1/0001 00:00 der zurückgegebene Wert nicht NULL.

Fehler "Sie können eine Transaktion nicht mit einer anderen Isolationsstufe starten, als für die aktuelle Transaktion bereits festgelegt ist"

Fehlercode: -2147220989
Fehlermeldung: Sie können keine Transaktion mit einer anderen Isolationsstufe starten, als für die aktuelle Transaktion bereits festgelegt ist.

Plug-Ins sollen Geschäftslogik unterstützen. Das Ändern eines Teils des Datenschemas in einem synchronen Plug-In wird nicht unterstützt. Diese Vorgänge dauern häufig länger und können dazu führen, dass zwischengespeicherte Metadaten, die von Anwendungen verwendet werden, nicht mehr synchron sind. Diese Vorgänge können jedoch in einem Plug-In-Schritt ausgeführt werden, der für die asynchrone Ausführung registriert ist.

Bekanntes Problem: Der Nameswert "Activity.RegardingObjectId" wurde beim Plug-In nicht festgelegt.

Das häufigste Symptom dieses Problems ist, dass das Feld "Regarding " in einem Aktivitätsdatensatz anstelle des Werts des primären Namensattributes anzeigt (No Name) .

Innerhalb eines Plug-Ins können Sie Suchattribute mit einem EntityReference-Wert festlegen. Die EntityReference.Name-Eigenschaft ist nicht erforderlich. In der Regel müssen Sie ihn beim Festlegen eines Nachschlage-Attributwerts nicht einschließen, da Dataverse ihn festlegt. Sie sollten werte wie diese während der PreOperation-Phase der Ereignispipeline festlegen. Weitere Informationen finden Sie unter Ereignisausführungspipeline.

Eine Ausnahme von dieser Regel ist das Festlegen der ActivityPointer.RegardingObjectId-Suche . Alle Entitätstypen, die von ActivityPointer abgeleitet sind, erben diese Suche. Dazu gehören standardmäßig Appointment, Chat, Email, Fax, Letter, PhoneCall, RecurringAppointmentMaster und alle benutzerdefinierten Tabellen, die als Aktivitätstypen erstellt wurden. Weitere Informationen finden Sie unter Aktivitätstabellen.

Wenn Sie diesen Wert in der PreOperation-Phase festlegen, wird der Nameswert nicht von Dataverse hinzugefügt. Der Wert ist NULL, und der formatierte Wert, der diesen Wert enthalten soll, ist beim Abrufen des Datensatzes nicht vorhanden.

Problemumgehung

Es gibt zwei Möglichkeiten, dieses Problem zu umgehen:

  1. Sie können den EntityReference.Name-Eigenschaftswert mit dem korrekten Feldwert für den primären Namen festlegen, bevor Sie den Wert des Nachschlageattributes festlegen.
  2. Sie können den Nachschlagewert in der Phase PreValidation anstelle von PreOperation festlegen.

Weitere Informationen