Résoudre les problèmes des plug-ins Dataverse
Cet article contient des informations sur les erreurs qui peuvent se produire pendant l’exécution du plug-in ou les erreurs Dataverse liées aux plug-ins et comment les éviter ou les corriger.
Erreur « Impossible de terminer la conversion de temps »
Code d’erreur : -2147220956
Message d’erreur : la conversion n’a pas pu être effectuée, car la propriété Type fournie n’a pas été définie correctement. Par exemple, lorsque la propriété Kind est DateTimeKind.Local, le fuseau horaire source doit être TimeZoneInfo.Local.
Cette erreur peut se produire lors d’un TimeZoneInfo.ConvertTimeToUtc(DateTime, TimeZoneInfo) appel dans le code de plug-in pour convertir une DateTime
valeur dans le fuseau horaire Santiago ou Volgograd en temps universel coordonné (UTC).
Cette erreur est due à une limitation de produit connue et il n’existe actuellement aucune solution de contournement.
Pour plus d’informations, consultez Spécifier les paramètres de fuseau horaire d’un utilisateur.
Erreur « Processus de travail de bac à sable bloqué »
Code d’erreur : -2147204723
Message d’erreur : l’exécution du plug-in a échoué, car le processus Worker de bac à sable a échoué. Cela est généralement dû à une erreur dans le code du plug-in.
Cette erreur signifie simplement que le processus Worker exécutant votre code de plug-in s’est bloqué. Votre plug-in peut être la raison du blocage, mais il peut également s’agir d’un autre plug-in s’exécutant simultanément pour votre organisation. Étant donné que le processus s’est écrasé, nous ne pouvons pas extraire d’informations plus spécifiques sur la raison pour laquelle il s’est écrasé. Mais après avoir examiné les données des vidages sur incident après le fait, nous avons constaté que cette erreur se produit généralement en raison de l’une des quatre raisons suivantes :
- Exception non gérée dans le plug-in
- Utilisation de threads pour mettre en file d’attente le travail sans essayer/intercepter le délégué de thread
- Erreur Stack Overflow dans le plug-in
- Le processus worker atteint la limite de mémoire
Exception non gérée dans le plug-in
Lorsque vous écrivez un plug-in, vous devez essayer d’anticiper les opérations susceptibles d’échouer et de les encapsuler dans un bloc try-catch. Lorsqu’une erreur se produit, vous devez utiliser la InvalidPluginExecutionException classe pour terminer correctement l’opération avec une erreur significative pour l’utilisateur.
Pour plus d’informations, consultez Gérer les exceptions dans les plug-ins.
Un scénario courant pour cette exception est l’utilisation de la méthode HttpClient.SendAsync ou HttpClient.GetAsync . Ces méthodes HttpClient sont des opérations asynchrones qui retournent une tâche. Pour travailler dans un plug-in dans lequel le code doit être synchrone, les utilisateurs peuvent utiliser le TResult> de tâche.< Propriété Result. Lorsqu’une erreur se produit, Result
retourne une valeur AggregateException. Un AggregateException
regroupement de plusieurs échecs en une seule exception, qui peut être difficile à gérer. Une meilleure conception consiste à utiliser Task<TResult>.GetAwaiter().GetResult(), car il propage les résultats en tant qu’erreur spécifique à l’origine de l’échec.
L’exemple suivant montre la bonne façon de gérer l’exception et un appel sortant à l’aide de la méthode HttpClient.GetAsync . Ce plug-in tente d’obtenir le texte de réponse d’un jeu d’URI dans la configuration non sécurisée d’une étape inscrite pour celle-ci.
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);
}
}
}
}
Utilisation de fils de discussion pour mettre le travail en file d’attente sans test/interception dans le délégué de fil de discussion
Vous ne devez pas utiliser de modèles d’exécution parallèles dans les plug-ins. Cet anti-modèle est décrit dans l’article de bonne pratique : n’utilisez pas l’exécution parallèle dans les plug-ins et les activités de flux de travail. L’utilisation de ces modèles peut entraîner des problèmes de gestion de la transaction dans un plug-in synchrone. Toutefois, une autre raison de ne pas utiliser ces modèles est que tout travail effectué en dehors d’un try
/catch
bloc dans un délégué de thread peut bloquer le processus de travail.
Important
Lorsque le processus de travail se bloque, l’exécution de votre plug-in et d’autres plug-ins en cours d’exécution dans ce processus se termine. Cela inclut les plug-ins que vous ne possédez pas ou ne gérez pas.
Application Insights au secours
Dans le passé, l’obtention de la trace de pile ou d’autres informations d’exécution pour les exceptions de plug-in non gérées du processus worker bloqué était impossible. Toutefois, Dataverse offre désormais la prise en charge des échecs d’exécution de journalisation dans Application Insights. Pour activer cette fonction, vous pouvez lier Application Insights à l’environnement dans lequel votre plug-in est inscrit. Une fois lié, la journalisation des blocages de plug-in se produit automatiquement.
Pour plus d’informations, consultez Exporter des données vers Application Insights.
Une fois qu’un environnement Application Insights a été lié, les données suivantes d’un incident de processus de travail sont disponibles pour résoudre le problème.
Pour accéder au rapport d’incident dans Application Insights, procédez comme suit :
- Lier Application Insights à votre environnement.
- Attendez qu’une exception de plug-in entraîne l’erreur d’incident du processus de travail.
- Dans le Centre d’administration Power Platform, accédez à Application Insights.
- Dans la page Application Insights, sélectionnez Échecs dans le volet gauche.
- Dans la page Échecs , sélectionnez Exceptions.
- Sous ID de problème d’exception, dans la liste globale , sélectionnez Microsoft.PowerPlatform.Dataverse.Plugin.PluginWorkerCrashException.
- Sur le côté droit de la page, sous Global, sélectionnez PluginWorkerCrashException. Vous verrez maintenant les détails de toutes les exceptions d’incident de processus worker enregistrées.
- Recherchez et sélectionnez l’exception souhaitée dans le volet gauche, et le rapport des détails de l’exception s’affiche sur le côté droit de la page (voir la capture d’écran précédente pour obtenir un exemple).
- Pour accéder à la trace de pile, développez CrashDetails dans le rapport.
Erreur de dépassement de capacité de pile dans le plug-in
Ce type d’erreur se produit le plus fréquemment juste après avoir apporté des modifications dans votre code de plug-in. Certaines personnes utilisent leur propre ensemble de classes de base pour rationaliser leur expérience de développement. Parfois, ces erreurs proviennent de modifications apportées aux classes de base dont dépend un plug-in particulier.
Par exemple, un appel récursif sans condition d’arrêt ou une condition d’arrêt, qui ne couvre pas tous les scénarios, peut provoquer cette erreur. Pour plus d’informations, consultez Notes de classe > StackOverflowException.
Vous devez examiner toutes les modifications de code qui ont été appliquées récemment pour le plug-in et tout autre code dont dépend le code du plug-in.
Exemple
Le code de plug-in suivant provoque un StackOverflowException
appel récursif sans limite. Malgré l’utilisation du suivi et la tentative de capture de l’erreur, le suivi et l’erreur ne sont pas retournés, car le processus de travail qui les traiterait se termine.
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");
}
}
}
Dans une étape de plug-in synchrone, le code de plug-in précédemment affiché retourne l’erreur suivante dans l’API web lorsque la demande est configurée pour inclure des détails supplémentaires avec des erreurs.
{
"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"
}
}
L’exemple suivant montre comment cette erreur est enregistrée dans le journal des traces du plug-in :
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& 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: #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& wcfExecInMs, Int64& initializeInMs, Int64& trackCallInMs, Int64& trackGoodReturnInMs, Int64& waitInMs, Int64& taskStartDelay)</OriginalException>
<TraceText i:nil="true" />
</OrganizationServiceFault>
Le processus worker atteint la limite de mémoire
Chaque processus Worker a une quantité limitée de mémoire. Il existe des conditions dans lesquelles plusieurs opérations simultanées qui incluent de grandes quantités de données peuvent dépasser la mémoire disponible et provoquer le blocage du processus Worker.
RetrieveMultiple avec données de fichier
Dans ce cas, le scénario courant est le moment où un plug-in s’exécute pour une RetrieveMultiple
opération où la demande inclut des données de fichier. Par exemple, lors de la récupération d’e-mails incluant des pièces jointes de fichiers. La quantité de données qui peuvent être retournées dans une requête comme celle-ci est imprévisible, car tout e-mail peut être lié à n’importe quel nombre de pièces jointes de fichier, et les pièces jointes peuvent varier en taille.
Lorsque plusieurs requêtes de même nature sont exécutées simultanément, la quantité de mémoire requise devient importante. Si la quantité de mémoire dépasse la limite, le processus se bloque. La clé pour empêcher cette situation est de limiter les RetrieveMultiple
requêtes qui incluent des entités avec des pièces jointes de fichiers associées. Récupérez les enregistrements en utilisant RetrieveMultiple
, mais récupérez tous les fichiers associés, le cas échéant, à l’aide des opérations Retrieve
.
Fuites de la mémoire
Un scénario moins courant est celui où le code du plug-in perd de la mémoire. Cette situation peut se produire lorsque le plug-in n’est pas écrit sans état, ce qui est une autre meilleure pratique. Pour plus d’informations, consultez Développer des implémentations de plug-in comme sans état. Lorsque le plug-in n’est pas sans état et qu’il existe une tentative d’ajouter continuellement des données à une propriété avec état comme un tableau, la quantité de données augmente jusqu’au point où elle utilise toute la mémoire disponible.
Erreurs de transaction
Il existe deux types courants d’erreurs liées à des transactions :
Code d’erreur : -2146893812
Message d’erreur : le code ISV a réduit le nombre de transactions ouvertes. Les plug-ins personnalisés ne doivent pas intercepter les exceptions des appels OrganizationService et continuer le traitement.
Code d’erreur : -2147220911
Message d’erreur : il n’existe aucune transaction active. Cette erreur est généralement due à des plug-ins personnalisés qui ignorent les erreurs des appels de service et continuent de traiter.
Note
L’erreur de niveau supérieur a été ajoutée récemment. Elle doit se produire immédiatement et dans le cadre d’un plug-in qui contient un problème. Une erreur de niveau inférieur peut toujours se produire dans différentes circonstances, impliquant généralement des activités de workflow personnalisées. Cela peut être dû à des problèmes dans un autre plug-in.
Chaque fois qu’une erreur liée à une opération de données se produit dans un plug-in synchrone, la transaction pour l’ensemble de l’opération est terminée.
Pour plus d’informations, consultez Conception de personnalisation évolutive dans Microsoft Dataverse.
Une cause courante est qu’un développeur croit qu’il peut tenter d’effectuer une opération qui peut réussir, de sorte qu’il encapsule cette opération dans un try
/catch
bloc et tente d’avaler l’erreur en cas d’échec.
Bien que ce modèle fonctionne pour une application cliente, dans l’exécution d’un plug-in, toute défaillance de l’opération de données entraîne la restauration de l’intégralité de la transaction. Vous ne pouvez pas avaler l’erreur, vous devez veiller à retourner toujours une InvalidPluginExecutionException.
Erreur « Erreur Sql : Expiration du délai d’exécution »
Code d’erreur : -2147204783
Message d’erreur : Erreur Sql : « Délai d’expiration de l’exécution expiré. La période d’expiration s’est écoulée avant la fin de l’opération ou le serveur ne répond pas.
Cause
Il existe une grande variété de raisons pour lesquelles une erreur de délai d’expiration SQL peut se produire. Trois d’entre eux sont décrits ici :
Blocage
La cause la plus courante d’une erreur de délai d’attente SQL est que l’opération attend les ressources bloquées par une autre transaction SQL. L’erreur est le résultat de Dataverse protégeant l’intégrité des données et des requêtes de longue durée qui affectent les performances des utilisateurs.
Le blocage peut être dû à d’autres opérations simultanées. Votre code peut fonctionner correctement dans un environnement de test et être toujours vulnérable aux conditions qui se produisent uniquement lorsque plusieurs utilisateurs lancent la logique dans votre plug-in.
Lorsque vous écrivez des plug-ins, il est essentiel de comprendre comment concevoir des personnalisations qui sont évolutives. Pour plus d’informations, consultez Conception de personnalisation évolutive dans Dataverse.
Opérations en cascade
Certaines actions que vous effectuez dans votre plug-in, telles qu’attribuer ou supprimer un enregistrement, peuvent initialiser la mise en cascade des opérations sur des enregistrements associés. Ces actions peuvent appliquer des verrous sur des enregistrements connexes entraînant le blocage des opérations de données suivantes, ce qui peut entraîner un délai d’expiration SQL.
Vous devez tenir compte de l’impact possible de ces opérations en cascade sur des opérations de données dans votre plug-in. Pour plus d’informations, consultez comportement des enregistrements de table.
Étant donné que ces comportements peuvent être configurés différemment entre les environnements, le comportement peut être difficile à reproduire, sauf si les environnements sont configurés de la même façon.
Index sur de nouvelles tables
Si le plug-in effectue des opérations à l’aide d’une table ou d’une colonne créée récemment, certaines fonctionnalités Azure SQL permettant de gérer les index peuvent faire une différence après quelques jours.
Erreurs dues aux privilèges de l’utilisateur
Dans une application cliente, vous pouvez désactiver les commandes que les utilisateurs ne sont pas autorisés à effectuer. Dans un plug-in, vous n’avez pas cette capacité. Votre code peut inclure une automatisation que l’utilisateur appelant n’a pas les privilèges à effectuer.
Vous pouvez enregistrer le plug-in pour s’exécuter dans le contexte d’un utilisateur connu pour disposer des privilèges appropriés en définissant la valeur Exécuter dans le contexte de l’utilisateur sur cet utilisateur. Vous pouvez également exécuter l’opération en empruntant l’identité d’un autre utilisateur. Pour plus d’informations, consultez l’article suivant :
Erreur lors de l’exécution dans le contexte d’un utilisateur désactivé
Lorsqu’un plug-in s’exécute dans le contexte d’un utilisateur désactivé, l’erreur suivante est retournée :
Message d’erreur : System.ServiceModel.FaultException'1[Microsoft.Xrm.Sdk.OrganizationServiceFault] : l’utilisateur avec SystemUserId=<User-ID> dans OrganizationContext=<Context> est désactivé. Les utilisateurs désactivés ne peuvent pas accéder au système. Envisagez d’activer cet utilisateur. En outre, les utilisateurs sont désactivés s’ils n’ont pas de licence qui leur est attribuée.
Pour résoudre cette erreur, vous pouvez exécuter une requête pour rechercher les étapes inscrites auprès de l’utilisateur désactivé, ainsi que le plug-in associé et SdkMessage
les détails.
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
Erreur « Taille du message dépassée lors de l’envoi du contexte au bac à sable »
Code d’erreur : -2147220970
Message d’erreur : la taille du message est dépassée lors de l’envoi du contexte au bac à sable. Taille du message : ### Mo
Cette erreur se produit lorsqu’une charge utile de message est supérieure à 116,85 Mo et qu’un plug-in est inscrit pour le message. Le message d’erreur inclut la taille de la charge utile qui a provoqué cette erreur.
La limite permet de s’assurer que les utilisateurs exécutant des applications ne peuvent pas interférer entre eux en fonction des contraintes de ressources. La limite permet de fournir un niveau de protection contre les charges utiles de messages inhabituellement volumineuses qui menacent la disponibilité et les caractéristiques de performances de la plateforme Dataverse.
116,85 Mo est suffisamment grand pour qu’il soit rare de rencontrer ce cas. Ce cas de figure plus probable peut se produire lorsque vous récupérez un enregistrement avec plusieurs enregistrements associés comprenant des fichiers binaires volumineux.
Si vous recevez cette erreur, vous pouvez :
- Supprimer le plug-in pour le message. Si aucun plug-in n’est inscrit pour le message, l’opération se termine sans erreur.
- Si l’erreur se produit dans un client personnalisé, vous pouvez modifier votre code afin qu’il ne tente pas d’effectuer le travail en une seule opération. Au lieu de cela, entrez le code pour extraire les données par petits morceaux.
Erreur « La clé donnée n’était pas présente dans le dictionnaire »
Dataverse utilise fréquemment des classes dérivées de la classe DataCollection<TKey,TValue> abstraite qui représente un ensemble de clés et de valeurs. Par exemple, avec des plug-ins, la IExecutionContextpropriété .InputParameters est dérivée ParameterCollection de la DataCollection<TKey,TValue> classe. Ces classes sont essentiellement des objets de dictionnaire permettant d’accéder à une valeur spécifique à l’aide du nom de la clé.
Codes d’erreur
Cette erreur se produit lorsque la valeur de clé dans le code n’existe pas dans la collection. Le résultat est une erreur d’exécution plutôt qu’une erreur de plateforme. Lorsque cette erreur se produit dans un plug-in, le code d’erreur dépend du fait que l’erreur a été interceptée.
Si le développeur a intercepté l’exception et retourné InvalidPluginExecutionException, comme décrit dans Gérer les exceptions dans les plug-ins, l’erreur suivante est retournée :
Code d’erreur : -2147220891
Message d’erreur : le code ISV a abandonné l’opération.
Toutefois, avec cette erreur, il est courant que le développeur ne l’intercepte pas correctement et que l’erreur suivante est retournée :
Code d’erreur : -2147220956
Message d’erreur : une erreur inattendue s’est produite à partir du code ISV.
Note
« ISV » (Independent Software Vendor) signifie pour Éditeur de logiciels indépendants.
Cause
Cette erreur se produit fréquemment au moment de la conception et peut être due à une faute d’orthographe ou à l’utilisation d’une casse incorrecte. Les valeurs de clé respectent la casse.
Au moment de l’exécution, l’erreur est fréquemment due au développeur en supposant que la valeur est présente lorsqu’elle n’est pas. Par exemple, dans un plug-in inscrit pour la mise à jour d’une table, seules les valeurs modifiées sont incluses dans la Entitycollection .Attributes
Résolution
Pour résoudre cette erreur, vous devez vérifier que la clé existe avant de tenter de l’utiliser pour accéder à une valeur.
Par exemple, lors de l’accès à une colonne de table, vous pouvez utiliser la Entityméthode .Contains(String) pour vérifier si une colonne existe dans une table, comme illustré dans le code suivant.
// 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"];
}
Certains développeurs utilisent la Entityméthode .GetAttributeValue<T>(String) pour éviter cette erreur lors de l’accès à une colonne de table. Cette méthode retourne la valeur par défaut du type si la colonne n’existe pas. Si la valeur par défaut est Null, cette méthode fonctionne comme prévu. Mais si la valeur par défaut ne retourne pas null, par exemple avec un DateTime
, la valeur retournée est 1/1/0001 00:00
plutôt que null.
Erreur « Vous ne pouvez pas démarrer une transaction avec un niveau d’isolation différent de celui déjà défini sur la transaction actuelle »
Code d’erreur : -2147220989
Message d’erreur : Vous ne pouvez pas démarrer une transaction avec un niveau d’isolation différent de celui déjà défini sur la transaction actuelle
Les plug-ins sont destinés à prendre en charge la logique métier. La modification d’une partie du schéma de données dans un plug-in synchrone n’est pas prise en charge. Ces opérations prennent souvent plus de temps et peuvent entraîner l’absence de synchronisation des métadonnées mises en cache utilisées par les applications. Toutefois, ces opérations peuvent être effectuées dans une étape de plug-in inscrite pour s’exécuter de manière asynchrone.
Problème connu : Valeur de nom Activity.RegardingObjectId non définie avec le plug-in
Le symptôme le plus courant de ce problème est que le champ En ce qui concerne un enregistrement d’activité s’affiche (No Name)
plutôt que la valeur d’attribut du nom principal.
Dans un plug-in, vous pouvez définir des attributs de recherche avec une valeur EntityReference . La propriété EntityReference.Name n’est pas obligatoire. En règle générale, vous n’avez pas besoin de l’inclure lors de la définition d’une valeur d’attribut de recherche, car Dataverse la définit. Vous devez définir des valeurs comme celle-ci pendant l’étape PreOperation du pipeline d’événements. Pour plus d’informations, consultez le pipeline d’exécution d’événements.
L’exception à cette règle est lors de la définition de la recherche ActivityPointer.RegardingObjectId . Tous les types d’entités dérivés de ActivityPointer
cette recherche héritent de cette recherche. Par défaut, ils incluent rendez-vous, conversation, courrier électronique, télécopie, lettre, PhoneCall, RecurringAppointmentMaster et toutes les tables personnalisées qui ont été créées en tant que types d’activités. Pour plus d’informations, consultez tables d’activité.
Si vous définissez cette valeur dans l’étape PreOperation , la valeur du nom n’est pas ajoutée par Dataverse. La valeur est Null et la valeur mise en forme qui doit contenir cette valeur n’est pas présente lorsque vous récupérez l’enregistrement.
Solution de contournement
Il existe deux façons de contourner ce problème :
- Vous pouvez définir la valeur de la propriété EntityReference.Name avec la valeur de champ de nom principal correcte avant de définir la valeur de l’attribut de recherche.
- Vous pouvez définir la valeur de recherche dans l’étape PreValidation plutôt que dans la phase PreOperation.