No use tipos de solicitud por lotes en complementos y actividades de flujo de trabajo
Categoría: uso, fiabilidad, rendimiento
Potencial de impacto: medio
Síntomas
Las experiencias de los usuarios se degradan y pueden producirse errores de tiempo de espera cuando se utilizan tipos de solicitudes por lotes en complementos y actividades de flujo de trabajo que se producen dentro de operaciones sincrónicas.
Las siguientes clases de solicitudes de mensajes se consideran tipos de solicitudes por lotes porque realizan operaciones en varios registros dentro de una sola solicitud:
- ExecuteMultipleRequest
- ExecuteTransactionRequest
- CreateMultipleRequest
- UpdateMultipleRequest
- UpsertMultipleRequest
Instrucciones
Utilice estos mensajes por lotes en aplicaciones cliente para realizar operaciones en varios registros. No utilice estos mensajes dentro del código que Dataverse invoca durante la ejecución de otra operación: un complemento o actividad de flujo de trabajo registrado para un paso sincrónico.
Más concretamente, úselos en los siguientes casos:
Use ExecuteMultipleRequest para cargar datos o procesos externos de forma masiva dirigidos a ejecutar operaciones prolongadas (superiores a dos minutos).
Use ExecuteMultipleRequest para minimizar los viajes de ida y vuelta entre los servidores del cliente personalizado y Dataverse, para reducir la latencia total acumulada.
Use ExecuteTransactionRequest para clientes externos que requieren confirmar el lote de operaciones como una transacción o reversión de base de datos única y atómica si se producen excepciones. Tenga en cuenta un posible bloqueo de la base de datos durante la transacción prolongada.
Utilice mensajes de operaciones masivas (CreateMultipleRequest, UpdateMultipleRequest y UpsertMultipleRequest) para los mismos escenarios y para lograr un mayor nivel de rendimiento.
Patrones problemáticos
El siguiente ejemplo muestra el uso de ExecuteMultipleRequest en el contexto de un complemento.
Advertencia
Este escenario debe evitarse.
public class ExecuteMultipleRequestInPlugin : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
IOrganizationService service = factory.CreateOrganizationService(context.UserId);
QueryExpression query = new QueryExpression("account")
{
ColumnSet = new ColumnSet("accountname", "createdon"),
};
//Obtain the results of previous QueryExpression
EntityCollection results = service.RetrieveMultiple(query);
if (results != null && results.Entities != null && results.Entities.Count > 0)
{
ExecuteMultipleRequest batch = new ExecuteMultipleRequest();
foreach (Entity account in results.Entities)
{
account.Attributes["accountname"] += "_UPDATED";
UpdateRequest updateRequest = new UpdateRequest();
updateRequest.Target = account;
batch.Requests.Add(updateRequest);
}
service.Execute(batch);
}
else return;
}
}
Este ejemplo incluye el uso del tipo directamente con el método Execute
. Este tipo de uso puede darse en cualquier momento durante la ejecución de un complemento o una actividad de flujo de trabajo. Esto podría ser también en un método contenido en la misma clase o en otra distinta. No se limita a estar directamente contenido en la definición del método Execute
.
Información adicional
El objetivo del mensaje ExecuteMultiple
es minimizar acciones de ida y vuelta entre el cliente y el servidor en conexiones latencia alta. Los complementos se ejecutan directamente en el proceso de la aplicación o muy cerca cuando están en espacios aislados y la latencia no suele ser un problema. El código del complemento tienen que ser operaciones concisas que se ejecuten rápidamente y minimicen el bloqueo para evitar superar los umbrales de tiempo de espera y asegurarse de que el sistema es dinámico en escenarios sincrónicos. Envíe cada solicitud directamente, en lugar de agruparlas en un lote y enviarlo como una sola solicitud.
Por ejemplo: foreach (request in requests) service.Execute(request)
En el servidor, las operaciones incluidas en una solicitud por lotes se ejecutan de forma secuencial y no se realizan en paralelo. Es así aunque la propiedad ExecuteMultipleSettings.ReturnResponses se haya establecido en false. Los programadores tienden a usar solicitudes por lotes de esta manera sabiendo que permiten el procesamiento en paralelo. La solicitudes por lotes no logran este objetivo.
La gente usa ExecuteTransactionRequest para asegurarse de que cada operación esté incluida en una transacción. Esto no es necesario en un paso de complemento sincrónico, porque el complemento ya se está ejecutando en la transacción de base de datos, lo que no hace necesario utilizar el mensaje ExecuteTransaction
.
Vea también
Marco de trabajo de eventos
Limitaciones al tiempo de ejecución
Ejemplo: ejecutar varias solicitudes usando SDK para .NET
Ejecutar mensajes en una sola transacción de la base de datos
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).