Usar mensajes de operación en masa

Para obtener el mejor rendimiento al realizar operaciones en varias filas de una tabla de Microsoft Dataverse, use uno de los mensajes de operaciń masiva siguientes:

Nota

Para obtener orientación sobre las opciones al realizar operaciones masivas, como cuándo usar estas API en comparación con las API por lotes como ExecuteMultiple, consulte Optimizar el rendimiento para operaciones masivas.

Ejemplos

Los siguientes ejemplos de código muestran cómo usar los mensajes de operación masiva. Puede descargar los ejemplos de github.com/microsoft/PowerApps-Samples:

CreateMultiple

Crea múltiples registros del mismo tipo en una sola solicitud.

Usa la clase CreateMultipleRequest.

/// <summary>
/// Demonstrates the use of the CreateMultiple Message
/// </summary>
/// <param name="service">The authenticated IOrganizationService instance.</param>
/// <param name="recordsToCreate">A list of records of the same table to create.</param>
/// <returns>The Guid values of the records created.</returns>
static Guid[] CreateMultipleExample(IOrganizationService service,
    List<Entity> recordsToCreate)
{

    // Create an EntityCollection populated with the list of entities.
    EntityCollection entities = new(recordsToCreate)
    {
        // All the records must be for the same table.
        EntityName = recordsToCreate[0].LogicalName
    };

    // Instantiate CreateMultipleRequest
    CreateMultipleRequest createMultipleRequest = new()
    {
        Targets = entities,
    };

    // Send the request
    CreateMultipleResponse createMultipleResponse =
                (CreateMultipleResponse)service.Execute(createMultipleRequest);

    // Return the Ids of the records created.
    return createMultipleResponse.Ids;
}

UpdateMultiple

Actualiza múltiples registros del mismo tipo en una sola solicitud.

Al igual que cuando, actualice los registros individuales, los datos que envía con UpdateMultiple solo deben contener los valores que está cambiando. Obtenga información sobre cómo actualizar registros con SDK para .NET y actualizar registros con la API web.

Usa la clase UpdateMultipleRequest.

/// <summary>
/// Demonstrates the use of the UpdateMultiple message.
/// </summary>
/// <param name="service">The authenticated IOrganizationService instance.</param>
/// <param name="recordsToUpdate">A list of records to create.</param>
static void UpdateMultipleExample(IOrganizationService service, List<Entity> recordsToUpdate) {
    // Create an EntityCollection populated with the list of entities.
    EntityCollection entities = new(recordsToUpdate)
    {
        // All the records must be for the same table.
        EntityName = recordsToUpdate[0].LogicalName
    };

    // Use UpdateMultipleRequest
    UpdateMultipleRequest updateMultipleRequest = new()
    {
        Targets = entities,
    };

    service.Execute(updateMultipleRequest);
}

Registros duplicados en el parámetro UpdateMultiple Targets

No se admiten varios registros con la misma clave principal o valores clave alternativa en la carga útil con UpdateMultiple. Cuando más de un registro en el parámetro Targets se identifica de forma única mediante un primario o clave alternativa, la operación se realiza solo en el primer registro. Se ignoran todos los registros posteriores con los mismos valores clave en la carga útil. Este comportamiento es diferente de UpsertMultiple.

UpsertMultiple

Utilice Upsert para integrar datos con fuentes externas cuando no se sabe si la tabla existe en Dataverse o no. Las operaciones Upsert frecuentemente dependen de claves alternativas para identificar registros. Utilice UpsertMultiple para realizar operaciones de Upsert en masa.

Usa la clase UpsertMultipleRequest.

Este método UpsertMultipleExample estático depende de una tabla samples_bankaccount que tiene una columna de cadena con el nombre samples_accountname configurada como clave alternativa. También tiene una columna de cadena llamada samples_description. Este código utiliza el Constructor de entidad que establece keyName y keyValue para especificar el valor de clave alternativa.

/// <summary>
/// Demonstrates using UpsertMultiple with alternate key values
/// </summary>
/// <param name="service">The authenticated IOrganizationService instance</param>
static void UpsertMultipleExample(IOrganizationService service)
{
    var tableLogicalName = "samples_bankaccount";
    // samples_accountname string column is configued as an alternate key
    // for the samples_bankaccount table
    var altKeyColumnLogicalName = "samples_accountname";

    // Create one record to update with upsert
    service.Create(new Entity(tableLogicalName)
    {
        Attributes =
        {
            {altKeyColumnLogicalName, "Record For Update"},
            {"samples_description","A record to update using Upsert" }
        }
    });

    // Using the Entity constructor to specify alternate key
    Entity toUpdate = new(
            entityName: tableLogicalName,
            keyName: altKeyColumnLogicalName,
            // Same alternate key value as created record.
            keyValue: "Record For Update");
    toUpdate["samples_description"] = "Updated using Upsert";

    Entity toCreate = new(
        entityName: tableLogicalName,
        keyName: altKeyColumnLogicalName,
        keyValue: "Record For Create");
    toCreate["samples_description"] = "A record to create using Upsert";

    // Add the records to a collection
    EntityCollection records = new()
    {
        EntityName = tableLogicalName,
        Entities = { toUpdate, toCreate }
    };

    // Send the request
    UpsertMultipleRequest request = new()
    {
        Targets = records
    };

    var response = (UpsertMultipleResponse)service.Execute(request);

    // Process the responses:
    foreach (UpsertResponse item in response.Results)
    {
        Console.WriteLine($"Record {(item.RecordCreated ? "Created" : "Updated")}");
    }
}

Salida:

Record Updated
Record Created

La creación o actualización de un registro en este ejemplo depende de si existen registros con el valor sample_keyattribute coincidente. No se devuelven datos para indicar si se creó o actualizó un registro.

Ejemplos de SDK

Dentro de Muestra: SDK para .NET, Usar operaciones masivas, busque Proyecto UpsertMultiple

Disponibilidad

UpsertMultiple está disponible para tablas que admiten CreateMultiple y UpdateMultiple. Esto incluye todas las tablas elásticas. Las consultas encontradas en Disponibilidad con tablas estándar no arrojarán resultados para UpsertMultiple, pero puede usarlas para detectar si una tabla admite ambos CreateMultiple y UpdateMultiple.

Estas consultas no devolverán resultados para el mensaje UpsertMultiple. Una tabla que admita tanto CreateMultiple como UpdateMultiple admitirá UpsertMultiple.

Registros duplicados en el parámetro UpsertMultiple Targets

No se admiten varios registros con la misma clave principal o valores clave alternativa en la carga útil con UpsertMultiple. Cuando más de un registro en el parámetro Targets se identifica de forma única mediante un primario o clave alternativa, UpsertMultiple devolverá un error. Este comportamiento es diferente de UpdateMultiple.

Uso de tablas estándar y elásticas

Tanto las tablas estándar como las elásticas se benefician de un impulso de rendimiento significativo al usar estos mensajes de operaciones masivas, pero debe usarlos de manera diferente. En la tabla siguiente se resumen las diferencias.

Diferencia Estándar Elástico
Número de registros Las operaciones son más eficientes con una mayor cantidad de registros. No hay un límite en el número de registros, pero sí hay límites de tamaño del mensaje y de tiempo. Recomendamos enviar 100 - 1000 registros a la vez. Recomendamos enviar 100 registros a la vez.
Comportamiento de error Todas las operaciones retroceden en caso de error. El éxito parcial es posible.
Disponibilidad No todas las tablas estándar admiten estos mensajes. Hay mensajes disponibles para todas las tablas elásticas.
DeleteMultiple No disponible. Use en cambio la SDK clase BulkDeleteRequest o la API web Acción BulkDelete. Más información sobre cómo eliminar datos de forma masiva. Disponible usando el SDK Clase OrganizationRequest. La acción de la API web DeleteMultiple es privada, pero puede usarla ahora. Pronto se hará público.

El uso de tablas estándar y elásticas es diferente porque las tablas estándar usan Azure SQL y admiten transacciones. Las tablas elásticas usan Azure Cosmos DB, que no admite transacciones pero puede manejar grandes cantidades de datos a altos niveles de rendimiento con baja latencia. Las siguientes secciones ofrecen más detalles. Obtenga más información sobre las operaciones masivas en tablas elásticas.

Número de registros

La cantidad de registros que debe incluir con cada solicitud depende de si usa tablas estándar o elásticas.

Sugerencia

Tanto las tablas estándar como las elásticas tienen un mayor rendimiento cuando envía mensajes de operaciones masivas en paralelo.

Número de registros con tablas estándar

Las operaciones masivas en tablas estándar están optimizadas para funcionar en varias filas en una sola transacción. Las operaciones se vuelven más eficientes y el rendimiento aumenta en general, a medida que aumenta el número de operaciones por solicitud. Esta optimización también permite que cualquier paso de complemento que se registra para la operación masiva sea más eficiente. Cada vez que se invoca un complemento para una sola operación, se requieren algunos milisegundos para invocar la clase de complemento que contiene la lógica. Cuando se registra un complemento para un mensaje de operación masiva, la clase se invoca una vez y puede procesar todas las operaciones de manera más eficiente. Aprenda a escribir complementos para CreateMultiple y UpdateMultiple.

Este beneficio de rendimiento le brinda un incentivo para enviar la mayor cantidad de registros que pueda en cada solicitud. Sin embargo, a medida que aumenta la cantidad de registros, el tamaño de la solicitud también aumenta y lleva más tiempo procesar. Eventualmente, encontrará límites de tamaño de mensaje y de tiempo. Si alcanza estos límites, toda la operación falla. No hay un límite establecido en la cantidad de registros que puede enviar. Puede necesitar experimentar para encontrar el mejor número. En general, esperamos que 100 - 1000 registros por solicitud sea un lugar razonable para comenzar si el tamaño de los datos del registro es pequeño y no hay complementos. Los tipos de errores que puede encontrar generalmente se pueden abordar enviando menos registros con cada solicitud. Le recomendamos que incluya la posibilidad de configurar el número de entidades enviadas para que puedas adaptarte enviando menos.

Número de registros con tablas elásticas

Debido a que no hay transacción con tablas elásticas, no hay beneficio de rendimiento al tratar de enviar un gran número de registros por solicitud. Recomendamos que envíe 100 operaciones por solicitud y enviar solicitudes en paralelo para lograr el máximo rendimiento.

Comportamiento de error

El comportamiento cuando se producen errores es diferente en función de si utiliza tablas estándar o elásticas.

Comportamiento de error con tablas estándar

Cualquier error que ocurra en una operación masiva con una tabla estándar hace que se revierta toda la operación. Debe usar solo operaciones en masa en tablas estándar cuando tenga un alto grado de confianza en que todas las operaciones se realizarán correctamente. Es posible que desee utilizar la clase ExecuteMultipleRequest del SDK o la API Web $batch para permitir la devolución del conjunto de operaciones si la operación masiva falla Si la tasa de éxito de los intentos iniciales es baja, esta estrategia genera un peor rendimiento. Solo use esta estrategia alternativa cuando espere que la mayoría de las operaciones funcionen correctamente.

Comportamiento de error con tablas elásticas

Con tablas elásticas, una operación masiva puede tener éxito parcialmente. Puede usar los detalles del error para identificar qué registros fallaron.

Cuando usa el SDK para realizar una operación masiva en una tabla elástica, se lanza una FaultException de tipo OrganizationServiceFault si ocurre un error. Use el código siguiente para obtener el estado de cada registro.

if (ex.Detail.ErrorDetails.TryGetValue("Plugin.BulkApiErrorDetails", out object errorDetails))
{
    List<BulkApiErrorDetail> bulkApiErrorDetails = JsonConvert.DeserializeObject<List<BulkApiErrorDetail>>(errorDetails.ToString());
}

public class BulkApiErrorDetail
{
    public int RequestIndex { get; set; }
    public string Id { get; set; }
    public int StatusCode { get; set; }
}

Disponibilidad

La disponibilidad de mensajes de operaciones masivas depende de si usa tablas estándar o elásticas. Todas las tablas elásticas admiten los mensajes CreateMultiple, UpdateMultiple, UpsertMultiple y DeleteMultiple.

Vea también:

Disponibilidad con tablas estándar

Puede usar los mensajes de operaciones en bloque CreateMultiple y UpdateMultiple para tablas estándar personalizadas con muchas tablas estándar comunes, pero no todas. Debe probar si las tablas estándar individuales admiten estos mensajes. Los siguientes ejemplos muestran cómo hacerlo.

Utilice este método estático para detectar si una tabla determinada admite CreateMultiple o UpdateMultiple.

/// <summary>
/// Detect whether a specified message is supported for the specified table.
/// </summary>
/// <param name="service">The IOrganizationService instance.</param>
/// <param name="entityLogicalName">The logical name of the table.</param>
/// <param name="messageName">The name of the message.</param>
/// <returns></returns>
public static bool IsMessageAvailable(
    IOrganizationService service,
    string entityLogicalName,
    string messageName)
{
    QueryExpression query = new("sdkmessagefilter")
    {
        ColumnSet = new ColumnSet("sdkmessagefilterid"),
        Criteria = new FilterExpression(LogicalOperator.And)
        {
            Conditions = {
            new ConditionExpression(
                attributeName:"primaryobjecttypecode",
                conditionOperator: ConditionOperator.Equal,
                value: entityLogicalName)
            }
        },
        LinkEntities = {
            new LinkEntity(
                linkFromEntityName:"sdkmessagefilter",
                linkToEntityName:"sdkmessage",
                linkFromAttributeName:"sdkmessageid",
                linkToAttributeName:"sdkmessageid",
                joinOperator: JoinOperator.Inner)
            {
                    LinkCriteria = new FilterExpression(LogicalOperator.And){
                    Conditions = {
                        new ConditionExpression(
                            attributeName:"name",
                            conditionOperator: ConditionOperator.Equal,
                            value: messageName)
                        }
                    }
            }
        }
    };

    EntityCollection entityCollection = service.RetrieveMultiple(query);

    return entityCollection.Entities.Count.Equals(1);
}

Canalizaciones de mensajes fusionadas

Cada uno de los mensajes de operación masiva tiene un mensaje correspondiente que opera en filas individuales: Create, Update y Delete. Estos mensajes existen desde hace mucho tiempo y muchas organizaciones tienen una lógica personalizada que depende de los eventos que ocurren cuando se usan estos mensajes.

Un requisito clave de estos mensajes de operaciones masivas es que no se debe exigir a las organizaciones que mantengan lógica personalizada en dos lugares. Para tener la misma lógica personalizada y mantenerla en un solo lugar, hemos fusionado las canalizaciones de procesamiento de mensajes para estos mensajes. ¿Qué significa esto?

  • Cuando se usa un mensaje de operación masiva, los eventos Create y Update respectivos ocurren para cada instancia de Entity en el parámetro Targets. Todos los complementos u otros controladores de eventos para los eventos individuales correspondientes siguen funcionando como siempre. No necesita escribir nuevos complementos para administrar los eventos generados por estos mensajes.

  • Cuando se usa un mensaje de operación único, el evento de operación masiva respectivo ocurre con una EntityCollection que contiene una single Entity instancia pasada en el parámetro Targets. Puede mover cualquier lógica que responda a eventos de operación única a los eventos de operación masiva más eficientes y la lógica se aplica tanto para operaciones únicas como múltiples.

Antes de la introducción de los mensajes de operaciones masivas, toda la lógica personalizada estaba en los mensajes de operaciones individuales. Esa lógica debe seguir aplicándose cuando las aplicaciones cliente utilizan los mensajes de operaciones masivas. Para las tablas que se usan con operaciones masivas de gran volumen, le recomendamos que comience a mover cualquier lógica síncrona existente de eventos de mensajes únicos a eventos de operaciones masivas. Si está introduciendo una nueva lógica, use los eventos de operación masiva en lugar de los eventos de operación única.

Precaución

Con este diseño, la lógica duplicada se puede aplicar potencialmente en versiones únicas y múltiples de eventos. Dataverse no intenta evitar esto porque no podemos conocer su intención.

Es su responsabilidad asegurarse de que la misma lógica aplicada para la versión única de los eventos se migre a la versión múltiple del evento y se elimine de la versión única del evento. De lo contrario, la lógica se aplicará dos veces.

Aprenda a escribir complementos para CreateMultiple y UpdateMultiple.

Limitaciones

Tenga en cuenta las siguientes limitaciones cuando utilice mensajes de operaciones masivas.

Tamaño del mensaje y límites de tiempo

Con las tablas estándar, existe un incentivo de rendimiento para enviar más registros con cada solicitud. Sin embargo, la cantidad de registros que puede enviar está limitada por el tamaño de la carga útil y la cantidad de tiempo necesario para procesar la operación.

Límites de tamaño del mensaje

Cuando tiene un complemento registrado para cualquier mensaje, es posible que encuentre el error "Tamaño del mensaje excedido al enviar contexto a Sandbox" cuando el tamaño total de la solicitud supera los 116,85 MB. Con los mensajes de operaciones masivas, es más probable que alcance este límite a medida que envía cargas útiles más grandes.

Este error no ocurre si no hay un complemento registrado para el evento. Para evitar el error, deshabilite cualquier complemento o envíe su solicitud con el parámetro opcional BypassCustomPluginExecution.

Límites de tiempo

Si está utilizando ServiceClient de Dataverse, es posible que encuentre este error:

The request channel timed out attempting to send after 00:04:00. 
Increase the timeout value passed to the call to Request or increase the SendTimeout value on the Binding. 
The time allotted to this operation may have been a portion of a longer timeout.

El tiempo de espera predeterminado establecido con ServiceClient es de 4 minutos, que es mucho para cualquier operación síncrona. Puede cambiar este valor usando la propiedad estática ServiceClient.MaxConnectionTimeout. El valor de tiempo de espera predeterminado con CrmServiceClient es de 2 minutos.

Nota

Antes de aumentar los límites de tiempo, debe considerar reducir el número de registros pasados ​​en el parámetro Targets.

No compatible para su uso en complementos

En este momento, no admitimos el uso de mensajes de operaciones masivas en el código del complemento. Más información: No use los tipos de solicitud de lotes en las actividades de flujo de trabajo y los complementos.

Sin embargo, debe escribir complementos para los mensajes CreateMultiple y UpdateMultiple como se describe en Escribir complementos para CreateMultiple y UpdateMultiple.

Solucionar errores habituales

Si encuentra errores al utilizar operaciones masivas, consulte los siguientes artículos:

Preguntas más frecuentes (P+F)

Si no encuentra una respuesta a las preguntas que tiene sobre el uso de mensajes de operaciones masivas en este artículo, use el botón en la parte inferior de la página para Enviar y ver comentarios para esta página. Necesita una cuenta de GitHub para enviar comentarios.

¿Se fusionarán las lógicas Retrieve y RetrieveMultiple?

No planeamos cambiar el comportamiento del mensaje Retrieve y RetrieveMultiple. Estos han sido mensajes separados durante muchos años y los desarrolladores siempre han necesitado mantener la lógica para ellos por separado. Intentar fusionar la canalización de mensajes para ellos sería muy problemático. Además, desaconsejamos aplicar una lógica personalizada para estos mensajes debido al impacto que pueden tener en el rendimiento.

¿Cómo se aplican los límites de API?

Hay dos tipos de límites de API. Los mensajes de operación masiva no proporcionan ninguna forma de eludir cualquier tipo.

Límites de protección de servicio

Como se describe en Límites de la API de protección del servicio, los límites tienen tres facetas. Dos de estos límites se evalúan en una ventana deslizante de cinco minutos y se aplican al usar estos mensajes.

  • Número de solicitudes: cada mensaje de operación masiva cuenta como una sola solicitud que se acumula hasta el límite de 6000 solicitudes por usuario, por servidor, durante la ventana de cinco minutos. Debido a que estas solicitudes agrupan operaciones individuales, se reduce la probabilidad de alcanzar este límite.
  • Tiempo de ejecución: debido a que cada solicitud de mensaje de operación masiva generalmente toma más tiempo, y si está enviando solicitudes en paralelo, es más probable que alcance el límite de tiempo de ejecución, eso es 20 minutos por usuario, por servidor, durante la ventana de cinco minutos.

Límites de solicitud de Power Platform (derecho de API)

Estos límites se basan en los cambios de datos: operaciones Create, Update y Delete. Cada elemento incluido en el parámetro Targets de una solicitud de operación masiva se acumula en este límite. Más información sobre asignaciones y límites de solicitudes

Consulte también

Usar UpsertMultiple (versión preliminar)
Usar DeleteMultiple (versión preliminar)
Tablas elásticas
Escribir complementos para CreateMultiple y UpdateMultiple
Muestra: SDK para .NET, Usar operaciones masivas
Muestra: API web, Usar operaciones masivas
Ejemplo: complementos CreateMultiple y UpdateMultiple
Use estos mensajes con el SDK para .NET
Optimice el rendimiento para operaciones masivas