Udostępnij za pośrednictwem


Rozwiązywanie problemów z wtyczkami Usługi Dataverse

Ten artykuł zawiera informacje o błędach, które mogą wystąpić podczas wykonywania wtyczki lub błędy usługi Dataverse związane z wtyczkami oraz sposoby ich unikania lub naprawiania.

Błąd "Nie można ukończyć konwersji czasu"

Kod błędu: -2147220956
Komunikat o błędzie: Nie można ukończyć konwersji, ponieważ podana właściwość DataTime nie ma poprawnie ustawionej właściwości Kind. Na przykład gdy właściwość Kind ma wartość DateTimeKind.Local, źródłowa strefa czasowa musi mieć wartość TimeZoneInfo.Local.

Ten błąd może wystąpić podczas TimeZoneInfo.ConvertTimeToUtc(DateTime, TimeZoneInfo) wywołania w kodzie wtyczki w celu przekonwertowania DateTime wartości w strefie czasowej Santiago lub Wołgograd na uniwersalny czas koordynowany (UTC).

Ten błąd jest spowodowany znanym ograniczeniem produktu i obecnie nie ma obejścia.

Aby uzyskać więcej informacji, zobacz Określanie ustawień strefy czasowej dla użytkownika.

Błąd "Proces roboczy piaskownicy uległ awarii"

Kod błędu: -2147204723
Komunikat o błędzie: Wykonanie wtyczki nie powiodło się, ponieważ proces roboczy piaskownicy uległ awarii. Jest to zwykle spowodowane błędem w kodzie wtyczki.

Ten błąd oznacza po prostu, że proces roboczy z uruchomionym kodem wtyczki uległ awarii. Wtyczka może być przyczyną awarii, ale może to być również inna wtyczka uruchomiona współbieżnie dla organizacji. Ponieważ proces uległ awarii, nie możemy wyodrębnić bardziej szczegółowych informacji o przyczynie awarii. Jednak po zbadaniu danych z zrzutów awaryjnych po tym, jak okazało się, że ten błąd zwykle występuje z jednego z czterech powodów:

Nieobsługiwany wyjątek w wtyczki

Podczas pisania wtyczki należy spróbować przewidzieć, które operacje mogą zakończyć się niepowodzeniem i opakować je w bloku try-catch. W przypadku wystąpienia błędu należy użyć InvalidPluginExecutionException klasy , aby bezpiecznie zakończyć operację z błędem zrozumiałym dla użytkownika.

Aby uzyskać więcej informacji, zobacz Obsługa wyjątków w wtyczkach.

Typowym scenariuszem dla tego wyjątku jest użycie metody HttpClient.SendAsync lub HttpClient.GetAsync . Te metody HttpClient to operacje asynchroniczne, które zwracają zadanie. Aby pracować w wtyczki, w której kod musi być synchroniczny, użytkownicy mogą używać TResult> zadania<. Właściwość Result. Gdy wystąpi błąd, Result zwraca wyjątek AggregateException. Moduł AggregateException konsoliduje wiele błędów w jednym wyjątku, który może być trudny do obsługi. Lepszym rozwiązaniem jest użycie funkcji TResult> zadania<. GetAwaiter().GetResult(), ponieważ propaguje wyniki jako określony błąd, który spowodował błąd.

W poniższym przykładzie pokazano prawidłowy sposób zarządzania wyjątkiem i wywołaniem wychodzącym przy użyciu metody HttpClient.GetAsync . Ta wtyczka próbuje uzyskać tekst odpowiedzi dla identyfikatora URI ustawionego w niezabezpieczonej konfiguracji dla kroku zarejestrowanego dla niego.

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

Używanie wątków do pracy w kolejce bez try/catch w delegatu wątku

Nie należy używać wzorców wykonywania równoległego w wtyczkach. Ten antywzór jest wywoływany w artykule z najlepszymi rozwiązaniami: Nie używaj równoległego wykonywania w wtyczkach i działaniach przepływu pracy. Użycie tych wzorców może powodować problemy z zarządzaniem transakcją w wtyczki synchronicznej. Innym powodem, dla którego nie należy używać tych wzorców, jest to, że każda praca wykonywana poza blokiem w delegacie wątku może ulec awarii procesu roboczego try/catch .

Ważne

Gdy proces roboczy ulegnie awarii, wykonanie wtyczki i innych wtyczek aktualnie uruchomionych w tym procesie zakończy się. Obejmuje to wtyczki, których nie posiadasz ani nie obsługujesz.

Usługa Application Insights do ratowania

W przeszłości uzyskanie śladu stosu lub innych informacji o wykonaniu dla nieobsługiwanych wyjątków wtyczek z procesu roboczego, które uległy awarii, było niemożliwe. Jednak usługa Dataverse oferuje teraz obsługę błędów wykonywania rejestrowania w usłudze Application Insights. Aby włączyć tę funkcję, możesz połączyć usługę Application Insights ze środowiskiem, w którym jest zarejestrowana wtyczka. Po połączeniu rejestrowanie awarii wtyczki odbywa się automatycznie.

Aby uzyskać więcej informacji, zobacz Eksportowanie danych do usługi Application Insights.

Po połączeniu środowiska usługi Application Insights następujące dane awarii procesu roboczego będą dostępne do rozwiązania problemu.

Przykład raportu awarii wtyczki usługi Application Insights.

Aby przejść do raportu o awarii w usłudze Application Insights, wykonaj następujące kroki:

  1. Połącz usługę Application Insights ze środowiskiem.
  2. Poczekaj, aż wyjątek wtyczki spowoduje wystąpienie błędu awarii procesu roboczego.
  3. W centrum administracyjnym platformy Power Platform przejdź do usługi Application Insights.
  4. Na stronie Application Insights wybierz pozycję Błędy w panelu po lewej stronie.
  5. Na stronie Błędy wybierz pozycję Wyjątki.
  6. W obszarze Identyfikator problemu wyjątku na liście Ogólne wybierz pozycję Microsoft.PowerPlatform.Dataverse.Plugin.PluginWorkerCrashException.
  7. Po prawej stronie w obszarze Ogólne wybierz pozycję PluginWorkerCrashException. Zostaną wyświetlone szczegóły wszystkich zarejestrowanych wyjątków awarii procesu roboczego.
  8. Wyszukaj i wybierz żądany wyjątek w panelu po lewej stronie, a raport szczegółów wyjątku zostanie wyświetlony po prawej stronie (zobacz powyższy zrzut ekranu, aby zapoznać się z przykładem).
  9. Aby uzyskać dostęp do śledzenia stosu, rozwiń węzeł CrashDetails w raporcie.

Błąd przepełnienia stosu w wtyczki

Ten typ błędu występuje najczęściej bezpośrednio po wprowadzeniu pewnych zmian w kodzie wtyczki. Niektórzy użytkownicy używają własnego zestawu klas bazowych, aby usprawnić środowisko programistyczne. Czasami te błędy pochodzą ze zmian w tych klasach bazowych, od których zależy określona wtyczka.

Na przykład wywołanie cyklicznego bez warunku zakończenia lub warunek zakończenia, który nie obejmuje wszystkich scenariuszy, może spowodować wystąpienie tego błędu. Aby uzyskać więcej informacji, zobacz StackOverflowException Class > Uwagi.

Należy przejrzeć wszelkie zmiany kodu, które zostały ostatnio zastosowane dla wtyczki i dowolnego innego kodu, od którego zależy kod wtyczki.

Przykład

Poniższy kod wtyczki powoduje StackOverflowException wywołanie cyklicznego bez ograniczeń. Pomimo użycia śledzenia i próby przechwycenia błędu śledzenie i błąd nie są zwracane, ponieważ proces roboczy, który przetworzyłby je zakończone.

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

W kroku synchronicznego wtyczki pokazany wcześniej kod wtyczki zwraca następujący błąd w internetowym interfejsie API, gdy żądanie jest skonfigurowane w celu uwzględnienia dodatkowych szczegółów z błędami.

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

Poniżej przedstawiono sposób rejestrowania tego błędu w wtyczki Tracelog:

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>

Proces roboczy osiąga limit pamięci

Każdy proces roboczy ma ograniczoną ilość pamięci. Istnieją warunki, w których wiele współbieżnych operacji obejmujących duże ilości danych może przekroczyć dostępną pamięć i spowodować awarię procesu roboczego.

RetrieveMultiple z danymi pliku

W tym przypadku typowym scenariuszem jest wykonanie wtyczki dla RetrieveMultiple operacji, w której żądanie zawiera dane pliku. Na przykład podczas pobierania wiadomości e-mail zawierających wszystkie załączniki plików. Ilość danych, które mogą być zwracane w zapytaniu takim, jest nieprzewidywalna, ponieważ każda wiadomość e-mail może być powiązana z dowolną liczbą załączników plików, a załączniki mogą się różnić w rozmiarze.

Gdy wiele żądań o podobnym charakterze jest uruchamianych jednocześnie, ilość wymaganej pamięci staje się duża. Jeśli ilość pamięci przekroczy limit, proces ulega awarii. Kluczem do zapobiegania tej sytuacji jest ograniczenie RetrieveMultiple zapytań zawierających jednostki z powiązanymi załącznikami plików. Pobierz rekordy przy użyciu metody RetrieveMultiple, ale pobierz wszystkie powiązane pliki zgodnie z potrzebami przy użyciu poszczególnych Retrieve operacji.

Przecieki pamięci

Mniej typowym scenariuszem jest to, że kod w wtyczki przecieka pamięci. Taka sytuacja może wystąpić, gdy wtyczka nie jest zapisywana jako bezstanowa, co jest kolejnym najlepszym rozwiązaniem. Aby uzyskać więcej informacji, zobacz Develop Plugin implementations as stateless (Opracowywanie implementacji wtyczek jako bezstanowych). Gdy wtyczka nie jest bezstanowa i próbuje stale dodawać dane do właściwości stanowej, takiej jak tablica, ilość danych rośnie do punktu, w którym używa całej dostępnej pamięci.

Błędy transakcji

Istnieją dwa typowe typy błędów związanych z transakcjami:

Kod błędu: -2146893812
Komunikat o błędzie: Kod niezależnego dostawcy oprogramowania zmniejszył liczbę otwartych transakcji. Niestandardowe wtyczki nie powinny przechwytywać wyjątków z wywołań organizationService i kontynuować przetwarzanie.

Kod błędu: -2147220911
Komunikat o błędzie: Brak aktywnej transakcji. Ten błąd jest zwykle spowodowany przez niestandardowe wtyczki, które ignorują błędy wywołań usług i kontynuują przetwarzanie.

Uwaga 16.

Ostatnio dodano najwyższy błąd. Powinna nastąpić natychmiast i w kontekście wtyczki, która zawiera problem. Dolny błąd może nadal występować w różnych okolicznościach, zazwyczaj obejmujących niestandardowe działania przepływu pracy. Może to być spowodowane problemami w innej wtyczki.

Za każdym razem, gdy wystąpi błąd związany z operacją danych w ramach synchronicznej wtyczki, transakcja dla całej operacji zostanie zakończona.

Aby uzyskać więcej informacji, zobacz Skalowalny projekt dostosowywania w usłudze Microsoft Dataverse.

Częstą przyczyną jest to, że deweloper uważa, że może podjąć próbę wykonania operacji, która może zakończyć się powodzeniem, więc opakują tę operację w try/catch bloku i próbują połykać błąd w przypadku niepowodzenia.

Mimo że ten wzorzec może działać w przypadku aplikacji klienckiej, w ramach wykonywania wtyczki wszystkie błędy operacji danych kończą się wycofywaniem całej transakcji. Nie można połykać błędu, więc należy upewnić się, że zawsze zwracany jest InvalidPluginExecutionExceptionelement .

Błąd "Błąd SQL: Upłynął limit czasu wykonywania"

Kod błędu: -2147204783
Komunikat o błędzie: Błąd SQL: "Upłynął limit czasu wykonywania. Upłynął limit czasu przed zakończeniem operacji lub serwer nie odpowiada".

Przyczyna

Istnieje wiele powodów, dla których może wystąpić błąd przekroczenia limitu czasu SQL. Trzy z nich zostały opisane tutaj:

blokowanie

Najczęstszą przyczyną błędu przekroczenia limitu czasu SQL jest to, że operacja oczekuje na zasoby zablokowane przez inną transakcję SQL. Błąd jest wynikiem ochrony integralności danych przez usługę Dataverse oraz od długotrwałych żądań wpływających na wydajność użytkowników.

Blokowanie może być spowodowane innymi operacjami współbieżnych. Kod może działać dobrze w izolacji w środowisku testowym i nadal być podatny na warunki, które występują tylko wtedy, gdy wielu użytkowników inicjuje logikę w wtyczki.

Podczas pisania wtyczek ważne jest, aby zrozumieć, jak projektować dostosowania skalowalne. Aby uzyskać więcej informacji, zobacz Skalowalny projekt dostosowywania w usłudze Dataverse.

Operacje kaskadowe

Niektóre akcje wykonywane w wtyczki, takie jak przypisywanie lub usuwanie rekordu, mogą inicjować kaskadowe operacje na powiązanych rekordach. Te akcje mogą stosować blokady na powiązanych rekordach, co powoduje zablokowanie kolejnych operacji danych, co z kolei może prowadzić do przekroczenia limitu czasu SQL.

Należy wziąć pod uwagę możliwy wpływ tych kaskadowych operacji na operacje na danych w wtyczki. Aby uzyskać więcej informacji, zobacz Zachowanie relacji tabeli.

Ponieważ te zachowania można skonfigurować inaczej między środowiskami, zachowanie może być trudne do odtworzenia, chyba że środowiska są skonfigurowane w taki sam sposób.

Indeksy w nowych tabelach

Jeśli wtyczka wykonuje operacje przy użyciu tabeli lub kolumny utworzonej niedawno, niektóre funkcje usługi Azure SQL do zarządzania indeksami mogą mieć wpływ po kilku dniach.

Błędy spowodowane uprawnieniami użytkownika

W aplikacji klienckiej można wyłączyć polecenia, których użytkownicy nie mogą wykonywać. W ramach wtyczki nie masz tej możliwości. Twój kod może zawierać automatyzację, którą użytkownik wywołujący nie ma uprawnień do wykonania.

Wtyczkę można zarejestrować, aby uruchomić w kontekście użytkownika znanego, że ma odpowiednie uprawnienia, ustawiając dla tego użytkownika wartość Uruchom w kontekście użytkownika. Możesz też wykonać operację, personifikując innego użytkownika. Aby uzyskać więcej informacji, zobacz:

Błąd podczas wykonywania w kontekście wyłączonego użytkownika

Gdy wtyczka jest wykonywana w kontekście wyłączonego użytkownika, zwracany jest następujący błąd:

Komunikat o błędzie: System.ServiceModel.FaultException'1[Microsoft.Xrm.Sdk.OrganizationServiceFault]: Użytkownik z identyfikatorem SystemUserId=<User-ID> w organizacjiContext=<Context> jest wyłączony. Wyłączone użytkownicy nie mogą uzyskać dostępu do systemu. Rozważ włączenie tego użytkownika. Ponadto użytkownicy są wyłączeni, jeśli nie mają przypisanej licencji.

Aby rozwiązać ten problem, możesz wykonać zapytanie w celu znalezienia kroków zarejestrowanych dla wyłączonego użytkownika, a także skojarzonych wtyczek i SdkMessage szczegółów.

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

Błąd "Przekroczono rozmiar komunikatu podczas wysyłania kontekstu do piaskownicy"

Kod błędu: -2147220970
Komunikat o błędzie: rozmiar komunikatu został przekroczony podczas wysyłania kontekstu do piaskownicy. Rozmiar komunikatu: ### Mb

Ten błąd występuje, gdy ładunek komunikatu jest większy niż 116,85 MB, a wtyczka jest zarejestrowana dla komunikatu. Komunikat o błędzie zawiera rozmiar ładunku, który spowodował ten błąd.

Limit pomaga zagwarantować, że użytkownicy z uruchomionymi aplikacjami nie będą mogli ingerować w siebie na podstawie ograniczeń zasobów. Limit pomaga zapewnić poziom ochrony przed niezwykle dużymi ładunkami komunikatów, które zagrażają dostępności i wydajności platformy Dataverse.

116,85 MB jest wystarczająco duży, aby rzadko spotykać ten przypadek. Najbardziej prawdopodobną sytuacją, w której ten przypadek może wystąpić, jest pobranie rekordu z wieloma powiązanymi rekordami, które zawierają duże pliki binarne.

Jeśli wystąpi ten błąd, możesz wykonać następujące czynności:

  1. Usuń wtyczkę dla komunikatu. Jeśli nie ma żadnych wtyczek zarejestrowanych dla komunikatu, operacja zostanie ukończona bez błędu.
  2. Jeśli błąd występuje w kliencie niestandardowym, możesz zmodyfikować kod, aby nie próbował wykonać pracy w ramach jednej operacji. Zamiast tego napisz kod, aby pobrać dane w mniejszych częściach.

Błąd "Podany klucz nie był obecny w słowniku"

Usługa Dataverse często używa klas pochodzących z klasy abstrakcyjnej DataCollection<TKey,TValue> , która reprezentuje kolekcję kluczy i wartości. Na przykład w przypadku wtyczek IExecutionContextwłaściwość .InputParameters jest pochodną ParameterCollection DataCollection<TKey,TValue> klasy . Te klasy są zasadniczo obiektami słownika, w których uzyskujesz dostęp do określonej wartości przy użyciu nazwy klucza.

Kody błędów

Ten błąd występuje, gdy wartość klucza w kodzie nie istnieje w kolekcji. Wynikiem jest błąd czasu wykonywania, a raczej błąd platformy. Gdy ten błąd występuje w wtyczki, kod błędu zależy od tego, czy błąd został przechwycony.

Jeśli deweloper przechwycił wyjątek i zwrócił InvalidPluginExecutionExceptionelement , zgodnie z opisem w temacie Obsługa wyjątków w wtyczkach, zwracany jest następujący błąd:

Kod błędu: -2147220891
Komunikat o błędzie: kod niezależnego dostawcy oprogramowania przerwał operację.

Jednak w przypadku tego błędu często deweloper nie przechwyci go prawidłowo i zwraca następujący błąd:

Kod błędu: -2147220956
Komunikat o błędzie: Wystąpił nieoczekiwany błąd z kodu niezależnego dostawcy oprogramowania.

Uwaga 16.

"ISV" oznacza niezależny dostawca oprogramowania.

Przyczyna

Ten błąd często występuje w czasie projektowania i może być spowodowany błędną pisownią lub użyciem nieprawidłowej wielkości liter. W wartościach klucza jest rozróżniana wielkość liter.

W czasie wykonywania błąd jest często spowodowany przez dewelopera przy założeniu, że wartość jest obecna, gdy nie jest. Na przykład w wtyczki zarejestrowanej na potrzeby aktualizacji tabeli tylko te wartości, które zostały zmienione, są uwzględniane w kolekcji Entity.Attributes

Rozwiązanie

Aby rozwiązać ten błąd, należy sprawdzić, czy klucz istnieje przed podjęciem próby użycia go w celu uzyskania dostępu do wartości.

Na przykład podczas uzyskiwania dostępu do kolumny tabeli można użyć Entitymetody .Contains(String) w celu sprawdzenia, czy kolumna istnieje w tabeli, jak pokazano w poniższym kodzie.

// 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"];
    }

Niektórzy deweloperzy używają Entitymetody .GetAttributeValue<T>(String) , aby uniknąć tego błędu podczas uzyskiwania dostępu do kolumny tabeli. Ta metoda zwraca wartość domyślną typu, jeśli kolumna nie istnieje. Jeśli wartość domyślna ma wartość null, ta metoda działa zgodnie z oczekiwaniami. Jeśli jednak wartość domyślna nie zwraca wartości null, na przykład z wartością DateTime, zwracana wartość jest 1/1/0001 00:00 zamiast wartości null.

Błąd "Nie można uruchomić transakcji z innym poziomem izolacji niż jest już ustawiony na bieżącej transakcji"

Kod błędu: -2147220989
Komunikat o błędzie: Nie można uruchomić transakcji z innym poziomem izolacji niż jest już ustawiony na bieżącej transakcji

Wtyczki mają obsługiwać logikę biznesową. Modyfikowanie jakiejkolwiek części schematu danych w ramach synchronicznej wtyczki nie jest obsługiwane. Te operacje często trwają dłużej i mogą spowodować, że buforowane metadane używane przez aplikacje przestaną być zsynchronizowane. Te operacje można jednak wykonać w kroku wtyczki zarejestrowanej w celu asynchronicznego uruchamiania.

Znany problem: Wartość nazwy Activity.RegardingObjectId nie jest ustawiona z wtyczką

Najczęstszym objawem tego problemu jest to, że pole Dotyczy w rekordzie działania pokazuje (No Name) , a nie wartość atrybutu nazwy podstawowej.

W ramach wtyczki można ustawić atrybuty odnośnika z wartością EntityReference . Właściwość EntityReference.Name nie jest wymagana. Zazwyczaj nie trzeba go uwzględniać podczas ustawiania wartości atrybutu odnośnika, ponieważ usługa Dataverse je ustawia. Należy ustawić wartości takie jak w etapie preoperacji potoku zdarzeń. Aby uzyskać więcej informacji, zobacz Potok wykonywania zdarzeń.

Wyjątkiem od tej reguły jest ustawienie odnośnika ActivityPointer.RegardingObjectId . Wszystkie typy jednostek, które pochodzą z ActivityPointer dziedziczenia tego odnośnika. Domyślnie obejmują one terminy, czat, wiadomości e-mail, faks, list, PhoneCall, CykliczneAppointmentMaster i wszystkie tabele niestandardowe, które zostały utworzone jako typy działań. Aby uzyskać więcej informacji, zobacz Tabele aktywności.

Jeśli ustawisz tę wartość na etapie PreOperation , wartość nazwy nie zostanie dodana przez usługę Dataverse. Wartość ma wartość null, a sformatowana wartość, która powinna zawierać tę wartość, nie jest obecna podczas pobierania rekordu.

Rozwiązanie

Istnieją dwa sposoby obejścia tego problemu:

  1. Można ustawić wartość właściwości EntityReference.Name z poprawną wartością pola nazwy podstawowej przed ustawieniem wartości atrybutu odnośnika.
  2. Wartość odnośnika można ustawić na etapie PreValidation, a nie na etapie PreOperation.

Więcej informacji