Solucionar problemas de plug-ins do Dataverse
Este artigo contém informações sobre erros que podem ocorrer durante a execução do plug-in ou erros do Dataverse relacionados a plug-ins e como evitá-los ou corrigi-los.
Erro "Não foi possível concluir a conversão de tempo"
Código de erro: -2147220956
Mensagem de erro: A conversão não pôde ser concluída porque o DataTime fornecido não tinha a propriedade Kind definida corretamente. Por exemplo, quando a propriedade Kind é DateTimeKind.Local, o fuso horário de origem deve ser TimeZoneInfo.Local.
Esse erro pode ocorrer durante uma TimeZoneInfo.ConvertTimeToUtc(DateTime, TimeZoneInfo) chamada no código do plug-in para converter um DateTime
valor no fuso horário de Santiago ou Volgogrado em UTC (Tempo Universal Coordenado).
Esse erro é causado por uma limitação conhecida do produto e atualmente não há solução alternativa.
Para obter mais informações, consulte Especificar configurações de fuso horário para um usuário.
Erro "Processo de trabalho de sandbox travado"
Código de erro: -2147204723
Mensagem de erro: A execução do plug-in falhou porque o processo do Sandbox Worker falhou. Isso geralmente ocorre devido a um erro no código do plug-in.
Esse erro significa simplesmente que o processo de trabalho que executa o código do plug-in falhou. Seu plug-in pode ser o motivo da falha, mas também pode ser outro plug-in em execução simultaneamente para sua organização. Como o processo travou, não podemos extrair informações mais específicas sobre o motivo pelo qual ele travou. Mas depois de examinar os dados dos despejos de memória após o fato, descobrimos que esse erro geralmente ocorre devido a um dos quatro motivos:
- Exceção sem tratamento no plug-in
- Usando threads para enfileirar o trabalho sem try/catch no delegado de thread
- Erro de estouro de pilha no plug-in
- O processo de trabalho atinge o limite de memória
Exceção sem tratamento no plug-in
Ao escrever um plug-in, você deve tentar antecipar quais operações podem falhar e envolvê-las em um bloco try-catch. Quando ocorre um erro, você deve usar a InvalidPluginExecutionException classe para encerrar normalmente a operação com um erro significativo para o usuário.
Para obter mais informações, consulte Manipular exceções em plug-ins.
Um cenário comum para essa exceção é ao usar o método HttpClient.SendAsync ou HttpClient.GetAsync . Esses métodos HttpClient são operações assíncronas que retornam uma tarefa. Para trabalhar em um plug-in em que o código precisa ser síncrono, as pessoas podem usar o Task<TResult>. Result propriedade. Quando ocorre um erro, Result
retorna um AggregateException. An AggregateException
consolida várias falhas em uma única exceção, o que pode ser difícil de lidar. Um design melhor é usar Task<TResult>. GetAwaiter().GetResult() porque propaga os resultados como o erro específico que causou a falha.
O exemplo a seguir mostra a maneira correta de gerenciar a exceção e uma chamada de saída usando o método HttpClient.GetAsync . Esse plug-in tenta obter o texto de resposta de um Uri definido na configuração não segura para uma etapa registrada para ele.
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);
}
}
}
}
Usando threads para enfileirar o trabalho sem try/catch no delegado de thread
Você não deve usar padrões de execução paralela em plug-ins. Esse antipadrão é chamado no artigo de práticas recomendadas: Não use a execução paralela em plug-ins e atividades de fluxo de trabalho. O uso desses padrões pode causar problemas no gerenciamento da transação em um plug-in síncrono. No entanto, outro motivo para não usar esses padrões é que qualquer trabalho feito fora de um try
/catch
bloco em um delegado de thread pode travar o processo de trabalho.
Importante
Quando o processo de trabalho falha, a execução do plug-in e de outros plug-ins atualmente em execução nesse processo será encerrada. Isso inclui plug-ins que você não possui ou mantém.
Application Insights para o resgate
No passado, era impossível obter o rastreamento de pilha ou outras informações de execução para exceções de plug-in sem tratamento do processo de trabalho com falha. No entanto, o Dataverse agora oferece suporte para registrar falhas de execução no Application Insights. Para habilitar essa função, você pode vincular o Application Insights ao ambiente em que o plug-in está registrado. Uma vez vinculado, o registro de falhas de plug-in ocorre automaticamente.
Para obter mais informações, consulte Exportar dados para o Application Insights.
Depois que um ambiente do Application Insights for vinculado, os dados a seguir de uma falha do processo de trabalho estarão disponíveis para solucionar o problema.
Para navegar até o relatório de falhas no Application Insights, siga estas etapas:
- Vincule o Application Insights ao seu ambiente.
- Aguarde até que uma exceção de plug-in resulte no erro de falha do processo de trabalho.
- No centro de administração do Power Platform, navegue até Application Insights.
- Na página Application Insights, selecione Falhas no painel esquerdo.
- Na página Falhas, selecione Exceções.
- Em ID do Problema de Exceção, na lista Geral, selecione Microsoft.PowerPlatform.Dataverse.Plugin.PluginWorkerCrashException.
- No lado direito da página, em Geral, selecione PluginWorkerCrashException. Agora você verá os detalhes de todas as exceções de falha do processo de trabalho registradas.
- Pesquise e selecione a exceção desejada no painel esquerdo, e o relatório de detalhes da exceção será exibido no lado direito da página (consulte a captura de tela anterior para obter um exemplo).
- Para acessar o rastreamento de pilha, expanda CrashDetails no relatório.
Erro de estouro de pilha no plug-in
Esse tipo de erro ocorre com mais frequência logo após você fazer algumas alterações no código do plug-in. Algumas pessoas usam seu próprio conjunto de classes base para otimizar sua experiência de desenvolvimento. Às vezes, esses erros se originam de alterações nas classes base das quais um plug-in específico depende.
Por exemplo, uma chamada recursiva sem uma condição de término ou uma condição de término, que não abrange todos os cenários, pode fazer com que esse erro ocorra. Para obter mais informações, consulte Comentários da classe > StackOverflowException.
Você deve revisar todas as alterações de código aplicadas recentemente para o plug-in e qualquer outro código do qual o código do plug-in dependa.
Exemplo
O código de plug-in a seguir causa um StackOverflowException
devido a uma chamada recursiva sem limites. Apesar do uso do rastreamento e da tentativa de capturar o erro, o rastreamento e o erro não são retornados porque o processo de trabalho que os processaria foi encerrado.
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");
}
}
}
Em uma etapa de plug-in síncrona, o código do plug-in mostrado anteriormente retorna o seguinte erro na API Web quando a solicitação é configurada para incluir detalhes adicionais com erros.
{
"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"
}
}
O seguinte mostra como esse erro é registrado no plug-in 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& 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>
O processo de trabalho atinge o limite de memória
Cada processo de trabalho tem uma quantidade finita de memória. Há condições em que várias operações simultâneas que incluem grandes quantidades de dados podem exceder a memória disponível e fazer com que o trabalhador do processo falhe.
RetrieveMultiple com dados de arquivo
O cenário comum, nesse caso, é quando um plug-in é executado para uma RetrieveMultiple
operação em que a solicitação inclui dados de arquivo. Por exemplo, ao recuperar e-mails que incluem anexos de arquivo. A quantidade de dados que podem ser retornados em uma consulta como essa é imprevisível porque qualquer email pode estar relacionado a qualquer número de anexos de arquivo e os anexos podem variar em tamanho.
Quando várias solicitações de natureza semelhante estão sendo executadas simultaneamente, a quantidade de memória necessária se torna grande. Se a quantidade de memória exceder o limite, o processo trava. A chave para evitar essa situação é limitar RetrieveMultiple
as consultas que incluem entidades com anexos de arquivo relacionados. Recupere os registros usando RetrieveMultiple
, mas recupere todos os arquivos relacionados conforme necessário usando operações individuais Retrieve
.
Perdas de memória
Um cenário menos comum é quando o código no plug-in está vazando memória. Essa situação pode ocorrer quando o plug-in não é escrito como sem estado, o que é outra prática recomendada. Para obter mais informações, consulte Desenvolver implementações de plug-in como sem estado. Quando o plug-in não é stateless e há uma tentativa de adicionar dados continuamente a uma propriedade stateful como uma matriz, a quantidade de dados cresce até o ponto em que ele usa toda a memória disponível.
Erros de transação
Existem dois tipos comuns de erros relacionados a transações:
Código de erro: -2146893812
Mensagem de erro: o código ISV reduziu a contagem de transações abertas. Os plug-ins personalizados não devem capturar exceções de chamadas OrganizationService e continuar o processamento.
Código de erro: -2147220911
Mensagem de erro: Não há nenhuma transação ativa. Esse erro geralmente é causado por plug-ins personalizados que ignoram erros de chamadas de serviço e continuam o processamento.
Observação
O erro superior foi adicionado mais recentemente. Isso deve ocorrer imediatamente e no contexto do plug-in que contém o problema. O erro inferior ainda pode ocorrer em diferentes circunstâncias, normalmente envolvendo atividades de fluxo de trabalho personalizadas. Pode ser devido a problemas em outro plug-in.
Sempre que um erro relacionado a uma operação de dados ocorre em um plug-in síncrono, a transação de toda a operação é encerrada.
Para obter mais informações, consulte Design de personalização escalonável no Microsoft Dataverse.
Uma causa comum é que um desenvolvedor acredita que pode tentar executar uma operação que pode ser bem-sucedida, então ele encapsula essa operação em umcatch
try
/bloco e tenta engolir o erro quando ele falha.
Embora esse padrão possa funcionar para um aplicativo cliente, na execução de um plug-in, qualquer falha na operação de dados resulta na reversão de toda a transação. Você não pode engolir o erro, portanto, certifique-se de sempre retornar um InvalidPluginExecutionException.
Erro "Erro de SQL: Tempo limite de execução expirado"
Código de erro: -2147204783
Mensagem de erro: Erro de SQL: 'Tempo limite de execução expirado. O período de tempo limite decorrido antes da conclusão da operação ou o servidor não está respondendo.'
Motivo
Há uma grande variedade de razões pelas quais um erro de tempo limite do SQL pode ocorrer. Três deles são descritos aqui:
Bloqueio
A causa mais comum para um erro de tempo limite do SQL é que a operação está aguardando recursos bloqueados por outra transação SQL. O erro é o resultado da proteção do Dataverse da integridade dos dados e de solicitações de longa duração que afetam o desempenho dos usuários.
O bloqueio pode ser devido a outras operações simultâneas. Seu código pode funcionar bem isoladamente em um ambiente de teste e ainda ser suscetível a condições que ocorrem apenas quando vários usuários estão iniciando a lógica em seu plug-in.
Ao escrever plug-ins, é essencial entender como projetar personalizações escalonáveis. Para obter mais informações, consulte Design de personalização escalonável no Dataverse.
Operações em cascata
Determinadas ações que você executa no plug-in, como atribuir ou excluir um registro, podem iniciar operações em cascata em registros relacionados. Essas ações podem aplicar bloqueios em registros relacionados, fazendo com que as operações de dados subsequentes sejam bloqueadas, o que, por sua vez, pode levar a um tempo limite do SQL.
Você deve considerar o possível impacto dessas operações em cascata nas operações de dados em seu plug-in. Para obter mais informações, consulte Comportamento da relação de tabela.
Como esses comportamentos podem ser configurados de forma diferente entre os ambientes, o comportamento pode ser difícil de reproduzir, a menos que os ambientes sejam configurados da mesma maneira.
Índices em novas tabelas
Se o plug-in estiver executando operações usando uma tabela ou coluna criada recentemente, alguns recursos do SQL do Azure para gerenciar índices poderão fazer a diferença após alguns dias.
Erros devido a privilégios de usuário
Em um aplicativo cliente, você pode desabilitar comandos que os usuários não têm permissão para executar. Em um plug-in, você não tem essa capacidade. Seu código pode incluir alguma automação que o usuário de chamada não tem privilégios para executar.
Você pode registrar o plug-in para ser executado no contexto de um usuário conhecido por ter os privilégios corretos definindo o valor Executar no Contexto do Usuário para esse usuário. Ou você pode executar a operação representando outro usuário. Para saber mais, veja:
Erro ao executar no contexto de um usuário desabilitado
Quando um plug-in é executado no contexto de um usuário desabilitado, o seguinte erro é retornado:
Mensagem de erro: System.ServiceModel.FaultException'1[Microsoft.Xrm.Sdk.OrganizationServiceFault]: o usuário com SystemUserId=<User-ID> em OrganizationContext=<Context> está desabilitado. Usuários desabilitados não podem acessar o sistema. Considere habilitar este usuário. Além disso, os usuários serão desabilitados se não tiverem uma licença atribuída a eles.
Para solucionar esse erro, você pode executar uma consulta para localizar as etapas registradas para o usuário desabilitado, bem como o plug-in e SdkMessage
os detalhes associados.
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
Erro "Tamanho da mensagem excedido ao enviar contexto para o Sandbox"
Código de erro: -2147220970
Mensagem de erro: o tamanho da mensagem foi excedido ao enviar contexto para o Sandbox. Tamanho da mensagem: ### Mb
Esse erro ocorre quando uma carga útil de mensagem é maior que 116,85 MB e um plug-in é registrado para a mensagem. A mensagem de erro inclui o tamanho da carga que causou esse erro.
O limite ajuda a garantir que os usuários que executam aplicativos não possam interferir uns com os outros com base em restrições de recursos. O limite ajuda a fornecer um nível de proteção contra cargas de mensagens excepcionalmente grandes que ameaçam as características de disponibilidade e desempenho da plataforma Dataverse.
116,85 MB é grande o suficiente para que seja raro encontrar esse caso. A situação mais provável em que esse caso pode ocorrer é quando você recupera um registro com vários registros relacionados que incluem arquivos binários grandes.
Se você receber esse erro, poderá:
- Remova o plug-in da mensagem. Se não houver plug-ins registrados para a mensagem, a operação será concluída sem erros.
- Se o erro estiver ocorrendo em um cliente personalizado, você poderá modificar seu código para que ele não tente executar o trabalho em uma única operação. Em vez disso, escreva o código para recuperar os dados em partes menores.
Erro "A chave fornecida não estava presente no dicionário"
O Dataverse frequentemente usa classes derivadas da classe abstrata DataCollection<TKey,TValue> que representa uma coleção de chaves e valores. Por exemplo, com plug-ins, a IExecutionContextpropriedade .InputParameters é derivada ParameterCollection da DataCollection<TKey,TValue> classe. Essas classes são essencialmente objetos de dicionário em que você acessa um valor específico usando o nome da chave.
Códigos do Erro
Esse erro ocorre quando o valor da chave no código não existe na coleção. O resultado é um erro de tempo de execução em vez de um erro de plataforma. Quando esse erro ocorre em um plug-in, o código de erro depende se o erro foi detectado.
Se o desenvolvedor tiver capturado a exceção e retornado InvalidPluginExecutionException, conforme descrito em Manipular exceções em plug-ins, o seguinte erro será retornado:
Código de erro: -2147220891
Mensagem de erro: O código ISV anulou a operação.
No entanto, com esse erro, é comum que o desenvolvedor não o capture corretamente e o seguinte erro seja retornado:
Código de erro: -2147220956
Mensagem de erro: Ocorreu um erro inesperado no código ISV.
Observação
"ISV" significa Fornecedor Independente de Software.
Motivo
Esse erro ocorre frequentemente em tempo de design e pode ser devido a um erro de ortografia ou ao uso de maiúsculas e minúsculas incorretas. Os valores-chave diferenciam maiúsculas de minúsculas.
Em tempo de execução, o erro geralmente ocorre porque o desenvolvedor assume que o valor está presente quando não está. Por exemplo, em um plug-in registrado para a atualização de uma tabela, somente os valores alterados são incluídos na Entitycoleção .Attributes .
Resolução
Para resolver esse erro, você deve verificar se a chave existe antes de tentar usá-la para acessar um valor.
Por exemplo, ao acessar uma coluna de tabela, você pode usar o Entitymétodo .Contains(String) para verificar se uma coluna existe em uma tabela, conforme mostrado no código a seguir.
// 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"];
}
Alguns desenvolvedores usam o Entitymétodo .GetAttributeValue<T>(String) para evitar esse erro ao acessar uma coluna da tabela. Esse método retornará o valor padrão do tipo se a coluna não existir. Se o valor padrão for nulo, esse método funcionará conforme o esperado. Mas se o valor padrão não retornar nulo, como com um DateTime
, o valor retornado será 1/1/0001 00:00
em vez de nulo.
Erro "Não é possível iniciar uma transação com um nível de isolamento diferente do que já está definido na transação atual"
Código de erro: -2147220989
Mensagem de erro: Você não pode iniciar uma transação com um nível de isolamento diferente do que já está definido na transação atual
Os plug-ins destinam-se a dar suporte à lógica de negócios. Não há suporte para a modificação de qualquer parte do esquema de dados em um plug-in síncrono. Essas operações geralmente demoram mais e podem fazer com que os metadados armazenados em cache usados pelos aplicativos fiquem fora de sincronia. No entanto, essas operações podem ser executadas em uma etapa de plug-in registrada para ser executada de forma assíncrona.
Problema conhecido: o valor do nome Activity.RegardingObjectId não definido com o plug-in
O sintoma mais comum desse problema é que o campo Referente a um registro de atividade é exibido (No Name)
, em vez do valor do atributo de nome principal.
Em um plug-in, você pode definir atributos de pesquisa com um valor EntityReference . A propriedade EntityReference.Name não é necessária. Normalmente, você não precisa incluí-lo ao definir um valor de atributo de pesquisa porque o Dataverse o define. Você deve definir valores como esse durante o estágio de Pré-Operação do pipeline de eventos. Para obter mais informações, consulte Pipeline de execução de eventos.
A exceção a essa regra é ao definir a pesquisa ActivityPointer.RegardingObjectId . Todos os tipos de entidade derivados herdam ActivityPointer
essa pesquisa. Por padrão, eles incluem Compromisso, Chat, Email, Fax, Carta, Telefone, RecurringAppointmentMaster e quaisquer tabelas personalizadas que foram criadas como tipos de atividade. Para obter mais informações, consulte Tabelas de atividades.
Se você definir esse valor no estágio PreOperation , o valor do nome não será adicionado pelo Dataverse. O valor é nulo e o valor formatado que deve conter esse valor não está presente quando você recupera o registro.
Solução alternativa
Há duas maneiras de contornar esse problema:
- Você pode definir o valor da propriedade EntityReference.Name com o valor correto do campo de nome principal antes de definir o valor do atributo de pesquisa.
- Você pode definir o valor de pesquisa no estágio de pré-validação em vez do estágio de pré-operação .