Compartir por


Escribir complementos para CreateMultiple y UpdateMultiple

Nota:

Los mensajes CreateMultiple y UpdateMultiple están siendo desplegados. Todas las tablas que admiten Create y Update finalmente admitirán CreateMultiple y UpdateMultiple, pero es posible que algunas tablas aún no las admitan. Más información sobre los mensajes de operación masiva

Debe escribir complementos para los mensajes CreateMultiple y UpdateMultiple con tablas donde pueda ser necesario crear o actualizar registros de forma masiva, o cuando el rendimiento en la creación y actualización de un gran número de registros sea importante. Es posible que sea necesario crear o actualizar de forma masiva aproximadamente todas las tablas que almacenan los datos empresariales.

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

¿Se requieren complementos de actualización?

No es necesario migrar los complementos para usar CreateMultiple y UpdateMultiple en lugar de Create y Update. La lógica sigue aplicándose cuando las aplicaciones usan CreateMultiple o UpdateMultiple. No es necesario migrar los complementos porque la canalización de procesamiento de mensajes de Dataverse combina la lógica de los 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 eligen optimizar el rendimiento mediante los CreateMultiple mensajes y UpdateMultiple , esperamos escribir complementos para que varias operaciones se conviertan en el estándar. Los complementos escritos para operaciones únicas serán la excepción.

¿Qué es diferente?

A continuación se muestran ciertas diferencias que debe administrar al migrar los complementos a los mensajes CreateMultiple y UpdateMultiple.

Destinos en lugar de Destino

La versión múltiple de estos mensajes tiene un Targets parámetro que es EntityCollection en lugar de un Target parámetro que es una sola entidad. El código del complemento debe recorrer en bucle las entidades de la colección y aplicar 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 EntityImageCollection. Estas imágenes de entidad solo están disponibles cuando se usa la interfaz IPluginExecutionContext4, que proporciona las propiedades PreEntityImagesCollection y PostEntityImagesCollection. Estos arreglos proporcionan acceso a las mismas imágenes de entidad en un arreglo que está sincronizado con EntityCollection.

Si usa la PluginBase clase que es el estándar al inicializar proyectos de complemento mediante herramientas de Power Platform, en el PluginBase.cs archivo debe reemplazar todas las instancias de IPluginExecutionContext por IPluginExecutionContext4 para que estas colecciones de imágenes de entidad estén disponibles para el 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. Estos datos se multiplican por el número de entidades pasadas en el parámetro Targets y contribuyen al tamaño total del mensaje que se envía al sandbox. 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 solo se ejecuta cuando se incluye cualquiera de los atributos seleccionados con la Target entidad que se está actualizando.
  • Con UpdateMultiple, el complemento se ejecuta cuando cualquiera de los atributos seleccionados se incluye en cualquiera de las entidades del Targets parámetro .

Importante

Para UpdateMultiple, no se puede suponer que todas las entidades del Targets parámetro contienen atributos que se usan en un filtro.

Example

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.

En este ejemplo se actualiza el sample_description atributo con información sobre si el sample_name valor 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 se producen en los complementos deben devolverse mediante InvalidPluginExecutionException. Cuando el complemento produce una excepción para los pasos registrados en los mensajes CreateMultiple y UpdateMultiple, debe identificar qué registro causó la falla del complemento. Para capturar esta información, use uno de los constructores siguientes:

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

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

Establecimiento de los detalles de la excepción

Para el mensaje UpdateMultiple, su código itera a través de la propiedad EntityCollectionTargets 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, se recomienda no establecer el valor de clave principal para cada registro. En la mayoría de los casos, debe permitir que el sistema establezca el valor de clave principal automáticamente porque los valores generados por el sistema están optimizados para mejorar el rendimiento.

En los casos en los que no se establece el valor de clave principal, si no hay ningún otro identificador único, es posible que tenga que devolver el índice del registro con errores en el parámetro EntityCollectionTargets o alguna combinación de valores que identifiquen de forma única el registro que produce un error. Por ejemplo, se puede agregar una clave denominada failedRecordIndex que indica el lugar del registro en EntityCollectiono cualquier otro identificador único útil para ayudar a exceptionDetails solucionar el error.

Obtención de detalles de la excepción

Al incluir detalles sobre la operación fallida en la propiedad InvalidPluginExecutionException.ExceptionDetails, la aplicación cliente puede obtenerlos de la propiedad OrganizationServiceFault.ErrorDetails a través de la propiedad FaultException<OrganizationServiceFault>.Detail. El código siguiente 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 usa la API web, puede obtener más detalles sobre los errores estableciendo el encabezado de Prefer: odata.include-annotations="*" solicitud.

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

Al implementar registros de pasos de complemento en soluciones, no hay forma de forzar que un registro de pasos se deshabilite o elimine. Esto hace que cambiar la lógica de una sola operación a un complemento de múltiples operaciones sea un desafío.

Al implementar 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 el tiempo en que no se aplica ninguna 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 lo deshabilita antes, habrá un período en el que no se aplicará ninguna lógica. Si deshabilita después, hay un período cuando se aplica lógica duplicada. En cualquier caso, la organización puede requerir tiempo de inactividad programado para asegurarse de que la lógica se aplica de forma coherente.

Para minimizar la duración de cualquiera de estas condiciones, se recomienda incluir lógica para deshabilitar los pasos que se van a reemplazar mediante la implementación de los nuevos complementos con package Deployer. Package Deployer proporciona la capacidad de ejecutar código personalizado antes, durante y después de importar el paquete en un entorno. Utilice este código para deshabilitar los registros de pasos existentes.

Consulte también

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