Solución de problemas de complementos
Este artículo contiene información sobre los errores que se puedan producir al ejecutar complementos y cómo corregirlos.
Error: el proceso de trabajador de espacio aislado se interrumpió
Código de error: -2147204723
Mensaje de error: The plug-in execution failed because the Sandbox Worker process crashed. This is typically due to an error in the plug-in code.
Este error significa simplemente que se ha bloqueado el proceso de trabajo que ejecuta el código de complemento. La razón del bloqueo puede ser el complemento, pero también puede deberse a otro complemento que se ejecute simultáneamente para la organización. Debido a que el proceso se ha bloqueado, no podemos extraer información más concreta sobre la causa del bloqueo. Pero, después de examinar los datos de los volcados de memoria después del incidente, descubrimos que esto suele ocurrir por una de las cuatro razones siguientes:
- Excepción no controlada en el complemento
- Error de desbordamiento de pila en el complemento
- Uso de subprocesos para poner en cola el trabajo sin bloque try/catch en el delegado de subproceso
- Agotamiento de la memoria del proceso de trabajo
Excepción no controlada en el complemento
Como se menciona en Administrar las excepciones en complementos, al escribir un complemento debe tratar de prever qué operaciones pueden generar errores y encapsularlas dentro de un bloque try-catch. Cuando se produzca algún error, debe usar InvalidPluginExecutionException para finalizar correctamente la operación con un error descriptivo para el usuario.
Un escenario común para esto es el uso de un método HttpClient.SendAsync o un método HttpClient.GetAsync, que son operaciones asincrónicas que devuelven un objeto Task. Para hacer que esto funcione en un complemento donde el código debe estar sincronizado, las personas pueden usar el Task<TResult>.Result Property. Cuando se produce un error, devuelve una AggregateException que consolida varios errores en una sola excepción, que puede ser difícil de tratar. Es mejor usar el diseño Task<TResult>.GetAwaiter().GetResult() porque propaga los resultados como el error específico que causó el error.
El siguiente ejemplo muestra la forma correcta de administrar la excepción y una llamada saliente mediante el método HttpClient.GetAsync. Este complemento intentará obtener el texto de respuesta para una URL establecida en la configuración no segura para un paso registrado para él.
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);
}
}
}
}
Error de desbordamiento de pila en el complemento
Este tipo de error ocurre con mayor frecuencia después de realizar algún cambio en el código del complemento. Algunas personas usan su propio conjunto de clases base para optimizar su experiencia de desarrollo. A veces, estos errores se originan por cambios en las clases base de las que depende un complemento concreto.
Por ejemplo, esto puede provocarlo una llamada recursiva sin una condición de terminación o una condición de terminación que no cubre todos los escenarios. Más información: Clase StackOverflowException > Comentarios
Debe revisar los cambios de código que se hayan aplicado recientemente al complemento y cualquier otro código del que dependa el código del complemento.
Ejemplo
El siguiente código de complemento provocará una StackOverflowException
por una llamada recursiva sin límites. A pesar del uso del rastreo y de intentar capturar el error, no se devolverán ni el rastreo ni el error porque el proceso de trabajo que los procesaría ha terminado.
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");
}
}
}
Cuando el código de complemento anterior se utiliza en un complemento sincrónico, la API web devolverá el siguiente error:
{
"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"
}
}
Así es como se registrará este error en el registro de seguimiento del complemento:
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>
Uso de subprocesos para poner en cola el trabajo sin bloque try/catch en el delegado de subproceso
No debe utilizar patrones de ejecución en paralelo en los complementos. Se indica esto en este artículo de procedimiento recomendado: No utilizar ejecución en paralelo en complementos y actividades de flujo de trabajo. El uso de estos patrones puede provocar problemas al administrar la transacción en un complemento sincrónico. Sin embargo, otro motivo para no usar estos patrones es que cualquier trabajo realizado fuera de un bloque try/catch en un subproceso delegado puede bloquear el proceso de trabajo.
Agotamiento de la memoria del proceso de trabajo
Cada proceso de trabajo tiene una cantidad finita de memoria. Hay condiciones en las que varias operaciones simultáneas que incluyen grandes cantidades de datos podrían exceder la memoria disponible y provocar el bloqueo del proceso de trabajo.
RetrieveMultiple con datos de archivo
El escenario común en este caso se da cuando un complemento se ejecuta para una operación RetrieveMultiple
en la que la solicitud incluye datos de archivo. Por ejemplo, al recuperar correos electrónicos, que incluyan archivos adjuntos. La cantidad de datos que se pueden devolver en una consulta como esta es impredecible, ya que cualquier correo electrónico puede estar relacionado con cualquier número de archivos adjuntos y el tamaño de los archivos adjuntos puede variar.
Cuando se ejecutan simultáneamente varias solicitudes de naturaleza similar, la cantidad de memoria se hace grande. Si se supera el límite, el proceso se bloqueará. La clave para prevenir esto es limitar las consultas RetrieveMultiple
que incluyen entidades con archivos adjuntos relacionados. Recupere los registros con RetrieveMultiple
, pero debe recuperar los archivos relacionados a medida que sea necesario mediante operaciones Retrieve
.
Pérdidas de memoria
Un escenario menos común es cuando el código del complemento pierde memoria. Esto puede ocurrir cuando el complemento no está escrito sin estado (otro procedimiento recomendado): Desarrollar implementaciones de IPlugin sin estado. Cuando el complemento no tiene estado y hay un intento de agregar datos continuamente a una propiedad con estado, como una matriz. La cantidad de datos crece hasta el punto en que usa toda la memoria disponible.
Errores de transacción
Hay dos tipos comunes de errores relacionados con las transacciones:
Código de error: -2146893812
Mensaje de error: ISV code reduced the open transaction count. Custom plug-ins should not catch exceptions from OrganizationService calls and continue processing.
Código de error: -2147220911
Mensaje de error: There is no active transaction. This error is usually caused by custom plug-ins that ignore errors from service calls and continue processing.
Nota
El error principal se agregó más recientemente. Debe aparecer inmediatamente y en el contexto del complemento que contiene el problema. El error inferior todavía puede aparecer en diferentes circunstancias, implicando normalmente actividades personalizadas del flujo de trabajo. Puede deberse a problemas en otro complemento.
Para comprender el mensaje, debe apreciar que en el momento en que se produce un error relacionado con una operación de datos en un complemento sincrónico, se terminará la transacción de toda la operación.
Más información: Diseño de personalización escalable en Microsoft Dataverse
La causa más común es simplemente que un desarrollador puede creer que puede intentar realizar una operación que podría tener éxito, por lo que encapsulan esa operación en un bloque try/catch e intentan tragar el error si produce error.
Si bien esto puede funcionar para una aplicación cliente, en la ejecución de un complemento los errores de operaciones de datos harán que se revierta toda la transacción. No se puede tragar el error, por lo que debe asegurarse de siempre devolver un InvalidPluginExecutionException.
Error: Error de Sql: Se agotó el tiempo de espera de ejecución
Código de error: -2147204783
Mensaje de error: Sql error: 'Execution Timeout Expired. The timeout period elapsed prior to completion of the operation or the server is not responding.'
Existe una gran variedad de razones por las que un error de tiempo de espera de SQL puede producirse.
Bloqueo
El bloqueo es la causa más común en un error de tiempo de espera de SQL, en el que la operación espera recursos que está bloqueando otra transacción SQL. El error es el resultado de que el sistema protege la integridad de los datos y las solicitudes de larga duración que impactan en el rendimiento para los usuarios.
El bloqueo puede deberse a otras operaciones simultáneas. El código puede funcionar bien en aislamiento en un entorno de prueba y seguir siendo susceptible a las condiciones que solo aparecerán cuando varios usuarios estén iniciando la lógica en el complemento.
Al escribir complementos, es importante comprender cómo diseñar personalizaciones que sean escalables. Más información: Diseño de personalización escalable en Dataverse
Operaciones en cascada
Algunas acciones que usted realiza en el complemento, como asignar o eliminar un registro, pueden iniciar operaciones en cascada en los registros relacionados. Estas acciones pueden aplicar bloqueos en registros relacionados, provocando el bloqueo de operaciones de datos posteriores, lo que a su vez pueden producir un tiempo de espera de SQL.
Debe considerar el impacto posible de estas operaciones en cascada en las operaciones de datos del complemento. Más información: Comportamiento de las relaciones de tabla
Puesto que estos comportamientos se pueden configurar de forma diferente entre los entornos, el comportamiento puede resultar difícil de reproducir a menos que los entornos estén configurados del mismo modo.
Índices en tablas nuevas
Si el complemento está realizando operaciones usando una tabla o una columna que se ha creado recientemente, algunas capacidades de Azure SQL para administrar índices pueden suponer una diferencia después de unos días.
Errores debidos a privilegios de usuario
En una aplicación cliente puede deshabilitar comandos que los usuarios no están autorizados a realizar. En un complemento no tiene esto. El código puede incluir alguna automatización para la que el usuario que llama no tiene privilegios.
Puede registrar el complemento para ejecutarse en el contexto de un usuario conocido para tener los privilegios correctos estableciendo el valor Ejecutar en contexto de usuario a ese usuario. O bien puede ejecutar la operación suplantando a otro usuario. Más información:
Error: Se ha superado el tamaño de mensaje al enviar contexto a espacio aislado
Código de error: -2147220970
Mensaje de error: Message size exceeded when sending context to Sandbox. Message size: ### Mb
Este error se produce cuando la carga de un mensaje es superior a 116,85 MB Y un complemento se registra para el mensaje. El mensaje de error incluirá el tamaño de la carga que produjo este error.
El límite le ayudará a asegurarse de que los usuarios que ejecuten aplicaciones no puedan interferir unos con otros basándose en limitaciones de recursos. El límite le ayudará a proporcionar cierto grado de protección contra cargas de mensaje excesivamente grandes que ponen en peligro las características de disponibilidad y rendimiento de la plataforma Dataverse.
116,85 MB es bastante grande, por lo que debería ser raro que se produzca este caso. La situación más probable donde puede producirse este caso es cuando se recupera un registro con varios registros relacionados que incluyen archivos binarios grandes.
Si encuentra este error, puede hacer lo siguiente:
- Quitar el complemento del mensaje. Si no complementos registrados para el mensaje, la operación se completará sin un error.
- Si el error se produce en un cliente personalizado, puede modificar el código de forma que no intente realizar el trabajo en una sola operación. En su lugar, escriba código para recuperar los datos en partes menores.
Error: la clave dada no estaba en el diccionario
Dataverse usa con frecuencia clases derivadas de la clase abstracta DataCollection<TKey,TValue> que representa una colección de claves y valores. Por ejemplo, con los complementos la propiedad IExecutionContext.InputParameters es una ParameterCollection derivada de la clase DataCollection<TKey,TValue>. Estas clases son esencialmente objetos de diccionario en las que puede tener acceso a un valor específico con el nombre de clave.
Códigos de error
Este error se produce cuando el valor de clave en código no existe en la colección. Se trata de un error en tiempo de ejecución en lugar de un error de plataforma. Cuando este error aparece en un complemento, el código de error dependerá de si el error se capturó.
Si el desarrollador capturó la excepción y devolvió una InvalidPluginExecutionException como se describe en Administrar excepciones en complementos, el siguiente error será devuelto:
Código de error: -2147220891
Mensaje de error: ISV code aborted the operation.
No obstante, con este error es común que el desarrollador no lo capture correctamente y el siguiente error será devuelto:
Código de error: -2147220956
Mensaje de error: An unexpected error occurred from ISV code.
Nota
"ISV" son las siglas de Fabricante independiente de software.
Causas
Este error aparece con frecuencia en tiempo de diseño y puede deberse a la falta de ortografía o al uso incorrecto de mayúsculas y minúsculas. Los valores de clave distinguen entre mayúsculas y minúsculas.
En tiempo de ejecución el error es debido con frecuencia a que el desarrollador asume que el valor estará presente, aunque no lo estará. Por ejemplo, en un complemento que se registra para la actualización de una tabla, solo se incluirán los valores que se cambien en la Entity.Attributes .
Prevención
Para evitar este error, debe comprobar que existe la clave antes de intentar usarla para tener acceso a un valor.
Por ejemplo, cuando tenga acceso a una columna de tabla, puede usar el método Entity.Contains(String) para comprobar si una columna existe en una tabla como se muestra en el siguiente código.
// 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"];
}
Algunos desarrolladores usan el método Entity.GetAttributeValue<T>(String) para evitar este error cuando acceden a una columna de tabla, pero tenga en cuenta que este método devolverá el valor predeterminado del tipo si no existe la columna. Si el valor predeterminado es nulo, esto funciona como se espera. Pero si el valor predeterminado no devuelve null, por ejemplo con un DateTime
, el valor devuelto será 1/1/0001 00:00
en lugar de null.
Error: no puede iniciar una transacción con un nivel de aislamiento diferente al que ya está configurado en la transacción actual
Código de error: -2147220989
Mensaje de error: You cannot start a transaction with a different isolation level than is already set on the current transaction
Los complementos están destinados a admitir la lógica empresarial. No se admite la modificación de ninguna parte del esquema de datos dentro del complemento síncrono. Estas operaciones suelen tardar más y pueden provocar que los metadatos almacenados en caché que utilizan las aplicaciones no estén sincronizados. Sin embargo, estas operaciones se pueden realizar en un paso de complemento registrado para ejecutarse de forma asincrónica.
Nota
¿Puede indicarnos sus preferencias de idioma de documentación? Realice una breve encuesta. (tenga en cuenta que esta encuesta está en inglés)
La encuesta durará unos siete minutos. No se recopilan datos personales (declaración de privacidad).