Escribir complementos para CreateMultiple y UpdateMultiple

Nota

Los mensajes CreateMultiple y UpdateMultiple se están desplegando. Todas las tablas que soportan Create y Update eventualmente serán compatibles con CreateMultiple y UpdateMultiple, pero es posible que algunas tablas aún no las admitan. Más información sobre los mensajes de operaciones masivas

Debe escribir complementos para los mensajes CreateMultiple y UpdateMultiple con tablas en las que es posible que sea necesario crear o actualizar registros en masa, o cuando el rendimiento en la creación y actualización de grandes cantidades de registros es bajo. importante. Es posible que casi todas las tablas que almacenan datos comerciales deban crearse o actualizarse de forma masiva.

Si tiene complementos existentes para los mensajes Create y Update para tablas como estas, debe migrarlos para usar CreateMultiple y UpdateMultiple en su lugar.

¿Es necesario actualizar los complementos?

No está obligado a migrar sus complementos para usar CreateMultiple y UpdateMultiple en lugar de Create y Update. Su lógica continúa aplicándose cuando las aplicaciones usan CreateMultiple o UpdateMultiple. No hay ningún requisito para migrar sus complementos porque el la canalización de procesamiento de mensajes de Dataverse fusiona la lógica para complementos escritos para la versión única o múltiple de estos mensajes.

Sin embargo, solo los complementos escritos para la versión múltiple de estos mensajes obtienen un aumento significativo del rendimiento. Con el tiempo, a medida que más desarrolladores opten por optimizar el rendimiento mediante los mensajes CreateMultiple y UpdateMultiple, esperamos que la escritura de complementos para múltiples operaciones se convierta en el estándar. Los complementos escritos para operaciones individuales serán la excepción.

¿Qué es diferente?

Las siguientes son algunas de las diferencias que debe administrar al migrar sus complementos para los mensajes CreateMultiple y UpdateMultiple.

Objetivos en lugar de Target

La versión múltiple de estos mensajes tiene un parámetro Targets que es un EntityCollection en lugar de un parámetro Target que es una sola Entidad. Su código de complemento debe recorrer las entidades de la colección y aplicar la lógica a cada una.

Imágenes de entidad

Las imágenes de entidad que se configuran en el registro de pasos para sus complementos son una matriz de EntityImageCollectionEntityImageCollection. Estas imágenes de entidad solo están disponibles cuando utiliza la interfaz IPluginExecutionContext4, que proporciona las propiedades PreEntityImagesCollection y PostEntityImagesCollection. Estas matrices brindan acceso a las mismas imágenes de entidad en una matriz que está sincronizada con EntityCollection.

Si está usando la clase PluginBase que es el estándar al inicializar proyectos de complementos usando Power Platform Tools, luego en el archivo PluginBase.cs debe reemplazar todas las instancias de IPluginExecutionContext con IPluginExecutionContext4 para que estas colecciones de imágenes de entidades estén disponibles para su complemento.

Importante

Cuando configura imágenes de entidades para pasos de complemento para CreateMultiple y UpdateMultiple, es importante que seleccione cuidadosamente qué datos de columna incluir. No seleccione la opción predeterminada de todas las columnas. Este dato se multiplica por el número de entidades pasadas en el parámetro Targets y contribuye al tamaño total del mensaje que se envía a la zona de pruebas. Puede alcanzar el límite en el tamaño del mensaje.

Filtros de atributo

Para un complemento registrado en Update o UpdateMultiple, puede especificar atributos de filtrado en el paso de registro.

  • Con Update, el complemento se ejecuta solo cuando alguno de los atributos seleccionados se incluye con la entidad Target que se está actualizando.
  • Con UpdateMultiple, el complemento se ejecuta cuando alguno de los atributos seleccionados se incluye en cualquiera de las entidades Targets.

Importante

Para UpdateMultiple, no puede asumir que cada entidad en el parámetro Targets contiene atributos que se usan en un filtro.

Ejemplo

Los siguientes ejemplos, uno con lógica básica para Update y otro con lógica para UpdateMultiple, acceden a imágenes de entidad registradas con el paso.

Este ejemplo actualiza el atributo sample_description con información sobre si el valor sample_name ha cambiado. Hace referencia a una imagen de entidad denominada example_preimage que se registró con el paso.

// Verify input parameters
if (context.InputParameters.Contains("Target") && context.InputParameters["Target"] is Entity entity)
{

   // Verify expected entity image from step registration
   if (context.PreEntityImages.TryGetValue("example_preimage", out Entity preImage))
   {

      bool entityContainsSampleName = entity.Contains("sample_name");
      bool entityImageContainsSampleName = preImage.Contains("sample_name");
      bool entityImageContainsSampleDescription = preImage.Contains("sample_description");

      if (entityContainsSampleName && entityImageContainsSampleName && entityImageContainsSampleDescription)
      {
            // Verify that the entity 'sample_name' values are different
            if (entity["sample_name"] != preImage["sample_name"])
            {
               string newName = (string)entity["sample_name"];
               string oldName = (string)preImage["sample_name"];
               string message = $"\\r\\n - 'sample_name' changed from '{oldName}' to '{newName}'.";

               // If the 'sample_description' is included in the update, do not overwrite it, just append to it.
               if (entity.Contains("sample_description"))
               {

                  entity["sample_description"] = entity["sample_description"] += message;

               }
               else // The sample description is not included in the update, overwrite with current value + addition.
               {
                  entity["sample_description"] = preImage["sample_description"] += message;
               }

               // Success:
               localPluginContext.Trace($"Appended to 'sample_description': \"{message}\" ");
            }
            else
            {
               localPluginContext.Trace($"Expected entity and preImage 'sample_name' values to be different. Both are {entity["sample_name"]}");
            }
      }
      else
      {
            if (!entityContainsSampleName)
               localPluginContext.Trace("Expected entity sample_name attribute not found.");
            if (!entityImageContainsSampleName)
               localPluginContext.Trace("Expected preImage entity sample_name attribute not found.");
            if (!entityImageContainsSampleDescription)
               localPluginContext.Trace("Expected preImage entity sample_description attribute not found.");
      }
   }
   else
   {
      localPluginContext.Trace($"Expected PreEntityImage: 'example_preimage' not found.");
   }
}
else
{
   if (!context.InputParameters.Contains("Target"))
      localPluginContext.Trace($"Expected InputParameter: 'Target' not found.");
   if (!(context.InputParameters["Target"] is Entity))
      localPluginContext.Trace($"Expected InputParameter: 'Target' is not Entity.");
}

Control de excepciones

Todos los errores que ocurren en sus complementos deben devolverse mediante InvalidPluginExecutionException. Cuando su complemento lanza una excepción para los pasos registrados en los mensajes CreateMultiple y UpdateMultiple, debe identificar qué registro provocó la falla del complemento. Para capturar esta información, necesita usar uno de los siguientes constructores:

Estos constructores le permiten agregar valores a la propiedad InvalidPluginExecutionException.ExceptionDetails, que no se puede configurar directamente.

Utilice el parámetro Dictionary<String,String> exceptionDetails del constructor para incluir información sobre el registro fallido y cualquier otra información relevante.

Establecer los detalles de la excepción

Para el mensaje UpdateMultiple, su código itera a través de la propiedad EntityCollection Targets y aplica la lógica a cada Entidad. Si se produce un fallo, puede pasar el Id del registro al constructor InvalidPluginExecutionException de la siguiente manera:

// in plugin code
foreach (Entity entity in Targets)
{
   // [...] When an error occurs:
   var exceptionDetails = new Dictionary<string, string>();
   exceptionDetails.Add("failedRecordId", (string)entity.Id);
   throw new InvalidPluginExecutionException("This is an error message.", exceptionDetails);
}

Agregue cualquier otra información que sea relevante a la falla como pares clave-valor de cadenas al parámetro exceptionDetails.

Para CreateMultiple, le recomendamos que no establezca el valor de la clave principal para cada registro. En la mayoría de los casos, debe permitir que el sistema establezca el valor de clave primaria automáticamente porque los valores generados por el sistema se optimizan para el máximo rendimiento.

En los casos en los que no se establece el valor de la clave principal, si no hay otro identificador único, es posible que deba devolver el índice del registro fallido en el parámetro EntityCollection Targets, o alguna combinación de valores que identifique de forma única el registro que falla. Por ejemplo, se puede agregar a failedRecordIndex una clave llamada EntityCollection que indica el lugar del registro en exceptionDetails, o cualquier otro identificador único útil, para ayudar a solucionar el problema.

Obtener los detalles de la excepción

Cuando incluye detalles sobre la operación fallida en la propiedad InvalidPluginExecutionException.ExceptionDetails, la aplicación cliente puede obtenerlos de OrganizationServiceFault.ErrorDetails mediante la propiedad FaultException<OrganizationServiceFault>.Detail. En el código siguiente se muestra cómo:


try
{
   // xMultiple request that triggers your plugin
}
catch (FaultException<OrganizationServiceFault> ex)
{
   ex.Detail.ErrorDetails.TryGetValue("failedRecordId", out object failedRecordId);
}

Si la aplicación cliente utiliza la API web, puede obtener más detalles sobre los errores configurando el encabezado de solicitud Prefer: odata.include-annotations="*".

Reemplace los complementos de una sola operación en las soluciones

Cuando implementa registros de pasos de complementos en soluciones, no hay forma de forzar la desactivación o eliminación de un registro de pasos. Eso hace que reemplazar la lógica de una sola operación a un complemento de operación múltiple sea un desafío.

Cuando implementa un nuevo paso de complemento en una solución para CreateMultiple o UpdateMultiple que reemplaza un paso de complemento para Create o Update, desea reducir la cantidad de tiempo cuando no se aplica lógica o lógica duplicada. Puede deshabilitar manualmente los pasos para Create o Update antes o después de instalar la solución. Si deshabilita antes, hay un período en el que no se aplica ninguna lógica. Si deshabilita después, hay un período en el que no se aplica lógica duplicada. En cualquier caso, la organización puede requerir un tiempo de inactividad programado para garantizar que la lógica se aplique de manera consistente.

Para minimizar la duración de cualquiera de estas condiciones, le recomendamos que incluya una lógica para deshabilitar cualquier paso que se reemplace al implementar los nuevos complementos con Package Deployer. Package Deployer proporicona la capacidad de ejecutar código personalizado antes, durante y después de que el paquete se importe a un entorno. Use este código para deshabilitar los registros de pasos existentes.

Consulte también

Ejemplo: complementos CreateMultiple y UpdateMultiple
Mensajes de operación masiva
Muestra: SDK para .NET, Usar operaciones masivas
Optimice el rendimiento para operaciones masivas

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).