Compartir a través de


Use Upsert para crear o actualizar un registro

Puede reducir la complejidad de los escenarios de integración de datos mediante el Upsert mensaje. Al cargar datos en Microsoft Dataverse desde un sistema externo, como en un escenario de integración de datos masivos, es posible que no sepa si ya existe un registro en Dataverse. En estos casos, no puede decidir si usar Update o Create mensaje. Primero debe recuperar el registro para comprobar si existe antes de realizar la operación adecuada. Puede reducir esta complejidad y cargar datos en Dataverse de manera más eficiente utilizando el mensaje Upsert.

Hay una penalización de rendimiento cuando se usa Upsert en lugar de Create. Si está seguro de que el registro no existe, use Create.

Nota

Aunque puede usar valores de clave principal con Upsert, se espera que use claves alternativas porque el caso de uso común es escenarios de integración de datos. Para obtener más información, consulte Uso de una clave alternativa para hacer referencia a un registro.

Actualización o inserción en tabla elástica

El comportamiento de la tabla elástica para Upsert difiere de las tablas estándar. Mediante el uso de tablas elásticas, la operación Upsert no llama al mensaje Create o Update según si ya existe el registro. Upsert aplica directamente los cambios en la entidad.

  • Si el registro existe: la operación sobrescribe todos los datos del registro con los datos de la entidad. No hay ningún evento de Update.
  • Si el registro no existe: la operación crea un nuevo registro. No hay evento Create.

Este comportamiento afecta a dónde se aplica la lógica empresarial con respecto a los eventos. Puede crear un registro mediante Create o Upsert. Puede actualizar un registro mediante Update o Upsert. Si necesita aplicar lógica consistentemente para Create o Update en tablas elásticas, también debe incluir esa lógica en Upsert. Para obtener más información, consulte Insertar o actualizar un registro en una tabla elástica.

Descripción del proceso upsert para las tablas estándar

El servidor procesa upsert mensajes. Las clases del SDK para .NET usan los mismos objetos que el servidor. Por lo tanto, la siguiente explicación usa el SDK para las clases de .NET para describir cómo el servidor procesa una instancia de clase UpsertRequest y devuelve una instancia de clase UpsertResponse .

En los pasos siguientes se describe la lógica de procesamiento en el servidor cuando recibe upsertRequest para una tabla estándar:

  1. La instancia UpsertRequest llega con la propiedad Target establecida en una instancia Entity que contiene los datos para una Create o Update operación.
  2. Si existe, Dataverse intenta buscar el registro mediante la propiedad Entity.Id de la instancia de Entity que está establecida en la propiedad Target. De lo contrario, usa los valores de clave alternativos de la propiedad Entity.KeyAttributes.
  3. Si existe el registro:
    1. Establezca el TargetEntity.Id en el valor de clave principal del registro encontrado.
    2. Quite los datos de la Target colección Entity.Attributes que use las mismas claves que la Target colección Entity.KeyAttributes.
    3. Llame a Update.
    4. Establezca la propiedad UpsertResponse.RecordCreated en false.
    5. Cree una entityReference a partir de la Target entidad como el valor de UpsertResponse.Target.
    6. Devuelve UpsertResponse.
  4. Si el registro no existe:
    1. Copie cualquier datos de TargetEntity.KeyAttributes que Targetno tenga ya en su colección Entity.Attributes en TargetEntity.Attributes.
    2. Llame a Create.
    3. Establezca UpsertResponse.RecordCreated en true.
    4. Cree una entityReference a partir de la Target entidad y el id resultado de la Create operación como valor de UpsertResponse.Target.
    5. Devuelve UpsertResponse.

En el diagrama siguiente se muestra el proceso en el servidor cuando recibe un UpsertRequest.

Captura de pantalla del flujo de proceso upsert para tablas estándar en Dataverse.

Orientación para redactar solicitudes

Al usar claves alternativas para identificar un registro, no incluya los datos de clave alternativos en la parte de la solicitud que representa los datos que se van a guardar.

Si usa la API web y no está familiarizado con el SDK para .NET, el proceso del lado servidor descrito anteriormente podría ser difícil de seguir. La API web no tiene el mismo modelo de objetos que los objetos del SDK usados en la descripción y el diagrama anterior, pero puede asignar los datos como se muestra en la tabla siguiente.

API Web SDK Descripción
Valores de clave en URL Propiedad Entity.KeyAttributes Contiene los datos de clave alternativa para identificar el registro.
Cuerpo de la solicitud La entidad definida en la propiedad UpsertRequest.Target Contiene los datos que se utilizarán para Create o Update.

Aunque el servidor procesa estas solicitudes como se ha descrito anteriormente, puede pensar en ello de esta manera:

  • Si el registro existe: El servidor quita el conjunto de datos en el cuerpo de la solicitud para esos valores de clave alternativos en la dirección URL, por lo que no hay ningún punto en incluirlo. Esta práctica garantiza que no pueda actualizar los valores clave alternativos de un registro cuando usa esos valores clave alternativos para identificarlo. Puede cambiar los valores de clave alternativos mediante la clave principal o un conjunto diferente de claves alternativas.
  • Si el registro no existe: El servidor usa cualquier valor de clave alternativo establecido en el cuerpo de la solicitud para crear el nuevo registro, incluso si los datos son diferentes de los valores especificados por las claves alternativas en la dirección URL. Si no hay datos de clave alternativos en el cuerpo de la solicitud, el servidor copia los datos de clave alternativos de la dirección URL en el cuerpo de la solicitud. Para evitar una situación en la que los valores de clave de la dirección URL y los valores de clave correspondientes del cuerpo no coinciden, no los incluya en el cuerpo.

Usar API web

Mediante la API web, puede iniciar los mensajes Upsert y Update enviando una solicitud HTTP PATCH a un recurso especificado EntitySet. Las claves de la dirección URL identifican el recurso.

La diferencia entre Upsert y Update depende de si incluye el encabezado de solicitud If-Match: *. Si incluye el encabezado de solicitud If-Match: * y ningún recurso coincide con los valores de clave de la dirección URL, la solicitud devuelve un código de estado 404 Not Found. El encabezado de solicitud If-Match: * asegura que la solicitud PATCH sea una operación Update.

Si no incluye el encabezado de If-Match: * solicitud, la PATCH solicitud se trata como una Upsert. La solicitud crea un nuevo registro si no encuentra ningún registro que coincida con las claves de la dirección URL. Sin embargo, a diferencia del SDK, la respuesta no indica si creó un registro. La respuesta de estado es 204 No Content en cualquier caso.

Si incluye un Prefer: return=representation encabezado de solicitud, el sistema devuelve un 201 Created estado para Createy un 200 OK estado para Update. Agregar este encabezado agrega una operación adicional Retrieve , por lo que afecta al rendimiento. Si utiliza esta opción, asegúrese de que la opción de consulta $select que agregue solo incluya el valor de clave principal. Para obtener más información, consulte:

Mediante una solicitud PATCH, también puede incluir el encabezado de solicitud If-None-Match: * para bloquear un Update si solo desea crear registros. Para obtener más información, consulte Limitar operaciones de upsert.

Código de ejemplo de API web

En los ejemplos siguientes, las operaciones Upsert se muestran utilizando una tabla con dos columnas de clave alternativas.

Creación con upsert

Esta solicitud crea un registro.

Solicitud:

PATCH [Organization Uri]/api/data/v9.2/example_records(example_key1=2,example_key2=2) HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
If-None-Match: null
Accept: application/json
Content-Type: application/json

{ "example_name": "2:2" }

Respuesta:

HTTP/1.1 204 No Content
OData-Version: 4.0
OData-EntityId: [Organization Uri]/api/data/v9.2/example_records(example_key1=2,example_key2=2)

Actualización con upsert

Esta solicitud actualiza el registro creado por la solicitud anterior.

Solicitud:

PATCH [Organization Uri]/api/data/v9.2/example_records(example_key1=2,example_key2=2) HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
If-None-Match: null
Accept: application/json
Content-Type: application/json

{ "example_name": "2:2 Updated" }

Respuesta:

HTTP/1.1 204 No Content
OData-Version: 4.0
OData-EntityId: [Organization Uri]/api/data/v9.2/example_records(example_key1=2,example_key2=2)

Nota

La respuesta es idéntica para las operaciones Crear o Actualizar.

Crear con upsert y return=representation preference

Cuando usa el encabezado Prefer: return=representation puede obtener un código de estado diferente en la respuesta para indicar si el registro se creó o actualizó.

La siguiente solicitud crea un nuevo registro y devuelve el estado 201 Created.

Solicitud:

PATCH [Organization Uri]/api/data/v9.2/example_records(example_key1=3,example_key2=3)?$select=example_recordid HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
If-None-Match: null
Accept: application/json
Prefer: return=representation
Content-Type: application/json

{ "example_name": "3:3" }

Respuesta:

HTTP/1.1 201 Created
Content-Type: application/json; odata.metadata=minimal
ETag: W/"71004878"
Preference-Applied: return=representation
OData-Version: 4.0

{
  "@odata.context": "[Organization Uri]/api/data/v9.2/$metadata#example_records(example_recordid)/$entity",
  "@odata.etag": "W/\"71004878\"",
  "example_recordid": "ef0d112e-d70e-ed11-82e5-00224822577b"
}

Actualizar con inserción y preferencia de devolución=representación

Esta solicitud actualiza el registro creado por la solicitud anterior y devuelve el estado 200 OK para mostrar que se trata de una operación de actualización.

Solicitud:

PATCH [Organization Uri]/api/data/v9.2/example_records(example_key1=3,example_key2=3)?$select=example_recordid HTTP/1.1
OData-MaxVersion: 4.0
OData-Version: 4.0
If-None-Match: null
Accept: application/json
Prefer: return=representation
Content-Type: application/json

{ "example_name": "3:3 Updated" }

Respuesta:

HTTP/1.1 200 OK
Content-Type: application/json; odata.metadata=minimal
ETag: W/"71004880"
OData-Version: 4.0

{
  "@odata.context": "[Organization Uri]/api/data/v9.2/$metadata#example_records(example_recordid)/$entity",
  "@odata.etag": "W/\"71004880\"",
  "example_recordid": "ef0d112e-d70e-ed11-82e5-00224822577b"
}

Uso del SDK para .NET

La aplicación cliente utiliza el método IOrganizationService.Execute con una instancia de UpsertRequest que tiene la propiedad Target configurada con una instancia de Entity que contiene los datos para una operación de Create o Update. Normalmente, se establece la propiedad Entity.KeyAttributes en la instancia de Entity con valores usados para identificar el registro mediante claves alternativas.

La propiedad UpsertResponse.RecordCreated indica si se creó el registro y UpsertResponse.Target contiene una referencia al registro que se creó o actualizó.

SDK para código de ejemplo de .NET

El archivo SampleMethod.cs en el ejemplo de Insertar registro utilizando Upsert contiene el siguiente método ProcessUpsert. Este método aplica el UpsertRequest mensaje en el contenido de un archivo XML para crear registros nuevos o actualizar los existentes.

public static void ProcessUpsert(CrmServiceClient service, String Filename)
{
    Console.WriteLine("Executing upsert operation.....");
    XmlTextReader tr = new XmlTextReader(Filename);
    XmlDocument xdoc = new XmlDocument();
    xdoc.Load(tr);
    XmlNodeList xnlNodes = xdoc.DocumentElement.SelectNodes("/products/product");

    foreach (XmlNode xndNode in xnlNodes)
    {
        String productCode = xndNode.SelectSingleNode("Code").InnerText;
        String productName = xndNode.SelectSingleNode("Name").InnerText;
        String productCategory = xndNode.SelectSingleNode("Category").InnerText;
        String productMake = xndNode.SelectSingleNode("Make").InnerText;

        //use alternate key for product
        Entity productToCreate = new Entity("sample_product", "sample_productcode", productCode);

        productToCreate["sample_name"] = productName;
        productToCreate["sample_category"] = productCategory;
        productToCreate["sample_make"] = productMake;
        var request = new UpsertRequest()
        {
            Target = productToCreate
        };

        try
        {
            // Execute UpsertRequest and obtain UpsertResponse.
            var response = (UpsertResponse)service.Execute(request);
            if (response.RecordCreated)
                Console.WriteLine("New record {0} is created!", productName);
            else
                Console.WriteLine("Existing record {0} is updated!", productName);
        }

        // Catch any service fault exceptions that Dataverse throws.
        catch (FaultException<Microsoft.Xrm.Sdk.OrganizationServiceFault>)
        {
            throw;
        }
    }
}

Vea también

Uso del seguimiento de cambios para sincronizar los datos con sistemas externos
Definir claves alternativas para una tabla
Usar una clave alternativa para hacer referencia a un registro