Actualizar y eliminar filas de tablas usando SDK para .NET

Este artículo incluye ejemplos que usan los de enlace en tiempo de ejecución y enlace en tiempo de compilación. Más información: Programación en tiempo de ejecución y en tiempo de compilación con SDK para .NET

Cada uno de los ejemplos usa una variable svc que representa una instancia de una clase que implementa los métodos en la interfaz IOrganizationService. Para obtener más información sobre las clases que admiten esta interfaz, consulte Interfaz IOrganizationService.

Importante

Al actualizar una fila de la tabla, solo incluya las columnas que está cambiando. La simple actualización de las columnas de una fila de la tabla que recuperó anteriormente actualizará cada columna aunque el valor no haya cambiado. Esto puede provocar eventos del sistema que pueden desencadenar la lógica de negocios que espera que los valores hayan cambiado realmente. Esto también puede hacer que parezca que las columnas se han actualizado en los datos de auditoría cuando en realidad no han cambiado.

Debería crear una nueva instancia de Entity, establezca el atributo de id. y cualquier valor de atributo que esté cambiando, y use esa instancia de entidad para actualizar la fila de la tabla.

Nota

La definición de columna incluye una propiedad RequiredLevel. Cuando se establece en SystemRequired, no puede establecer estas columnas en un valor nulo. Si intenta esto obtendrá el código de error -2147220989 con el mensaje Attribute: <attribute name> cannot be set to NULL.

Más información: Nivel de requisito de columna (atributo)

Actualización básica

Los dos ejemplos siguientes utilizan el Método IOrganizationService.Update para establecer valores de columna para una fila de la tabla que se recuperó previamente.

Use la propiedad Entity.Id para transferir el valor del identificador único de la fila recuperada para la instancia de entidad que se utiliza para realizar la operación de actualización.

Nota

Si intenta actualizar una fila sin un valor de clave principal, obtendrá el error: Entity Id must be specified for Update.

Si no tiene un valor de clave principal, también puede actualizar filas con claves alternativas. Más información: Actualización con clave alternativa

El siguiente ejemplo muestra el uso de la [clase de entidad](xref:Microsoft.Xrm.Sdk.Entity] para crear una cuenta mediante el Método IOrganizationService.Update.

var retrievedAccount = new Entity("account", new Guid("a976763a-ba1c-e811-a954-000d3af451d6"));

//Use Entity class with entity logical name
var account = new Entity("account");
account.Id = retrievedAccount.Id;
// set attribute values
// Boolean (Two option)
account["creditonhold"] = true;
// DateTime
account["lastonholdtime"] = DateTime.Now;
// Double
account["address1_latitude"] = 47.642311;
account["address1_longitude"] = -122.136841;
// Int
account["numberofemployees"] = 400;
// Money
account["revenue"] = new Money(new Decimal(2000000.00));
// Picklist (Option set)
account["accountcategorycode"] = new OptionSetValue(2); //Standard customer

//Update the account
svc.Update(account);

Usar la clase UpdateRequest

En lugar de usar el método IOrganizationService.Update, puede usar la clase de entidad de enlace tardío o la generada clases de entidad de enlace anticipado con la clase UpdateRequest estableciendo la instancia de la entidad en la propiedad UpdateRequest.Target y luego utilizando el método IOrganizationService.Execute.

Nota

La clase UpdateResponse no tiene propiedades. Aunque lo devuelve el método IOrganizationService.Execute, no es necesario referirse al mismo.

var request = new UpdateRequest()
{ Target = account };
svc.Execute(request);

Cuando utilizar la clase UpdateRequest

Debe usar la clase UpdateRequest si desea pasar parámetros opcionales. Hay dos casos donde es posible que necesite parámetros especiales.

Debe usar la clase UpdateRequest si desea especificar un comportamiento de la simultaneidad optimista. Más información: Comportamiento de simultaneidad optimista

Usar la clase UpdateMultipleRequest

La clase UpdateMultipleRequest es la forma más eficaz de actualizar varios registros en una sola solicitud. Más información: Operaciones masivas con mensajes

De manera similar a como puede Crear filas de tablas relacionadas en una sola operación, también puede actualizar las filas de la tabla relacionadas.

Para actualizar filas de tabla relacionadas, debe recuperar una fila con las filas relacionadas para poder acceder a los valores de id. Más información: Recuperar con filas relacionadas

Importante

Las actualizaciones de las filas se realizan en un orden específico. Primero, se procesan las filas de la tabla primaria y luego se procesan las filas de la tabla relacionadas. Si la fila principal realiza un cambio para una búsqueda o una columna de fila relacionada, y luego una fila relacionada actualiza la misma columna, se conserva el valor de la fila relacionada. En general, un valor de columna de búsqueda y su equivalente en Entity.RelatedEntities para la misma relación no deben usarse al mismo tiempo.

var account = new Entity("account");
account.Id = retrievedAccount.Id;

//Define relationships
var primaryContactRelationship = new Relationship("account_primary_contact");
var AccountTasksRelationship = new Relationship("Account_Tasks");

//Update the account name
account["name"] = "New Account name";

//Update the email address for the primary contact of the account
var contact = new Entity("contact");
contact.Id = retrievedAccount.RelatedEntities[primaryContactRelationship]
.Entities.FirstOrDefault().Id;
contact["emailaddress1"] = "someone_a@example.com";

List<Entity> primaryContacts = new List<Entity>();
primaryContacts.Add(contact);  
account.RelatedEntities.Add(primaryContactRelationship, new EntityCollection(primaryContacts));

// Find related Tasks that need to be updated
List<Entity> tasksToUpdate = retrievedAccount
.RelatedEntities[AccountTasksRelationship].Entities
.Where(t => t["subject"].Equals("Example Task")).ToList();

// A list to put the updated tasks
List<Entity> updatedTasks = new List<Entity>();

//Fill the list of updated tasks based on the tasks that need to but updated
tasksToUpdate.ForEach(t => {
var updatedTask = new Entity("task");
updatedTask.Id = t.Id;
updatedTask["subject"] = "Updated Subject";

updatedTasks.Add(updatedTask);
});

//Set the updated tasks to the collection
account.RelatedEntities.Add(AccountTasksRelationship, new EntityCollection(updatedTasks));

//Update the account and related contact and tasks
svc.Update(account);

Comprobar registros duplicados

Al actualizar una fila de la tabla, puede cambiar los valores para que la fila represente un duplicado de otra fila. Más información: Detectar datos duplicados usando SDK para .NET

Actualizar con clave alternativa

Si tiene un clave alternativa definido para una tabla, puede usarlo en lugar de la clave principal para actualizar una fila. No puede usar la clase enlazada en tiempo de compilación para especificar la clave alternativa. Debe usar el Entity(String, KeyAttributeCollection) constructor para especificar la clave alternativa.

Si desea usar enlaces de tipo de compilación, puede convertir Entity en una clase enlazada en tiempo de compilación mediante el método Entity.ToEntity<T>.

El siguiente ejemplo muestra cómo actualizar Account utilizando un clave alternativa definido para la columna accountnumber (atributo).

Importante

La mayoría de las tablas para datos profesionales no tienen definidas claves alternativas. Este método solo se puede utilizar cuando el entorno está configurado para definir un clave alternativa para una tabla.

var accountNumberKey = new KeyAttributeCollection();
accountNumberKey.Add(new KeyValuePair<string, object>("accountnumber", "123456"));

Account exampleAccount = new Entity("account", accountNumberKey).ToEntity<Account>();
exampleAccount.Name = "New Account Name";
svc.Update(exampleAccount);

Más información:

Actualizar y eliminar registros en tablas elásticas

Si está actualizando o eliminando datos de tabla elástica almacenados en particiones, asegúrese de especificar la clave de partición cuando acceda a esos datos. Más información: Particionamiento y escalado horizontal

Usar upsert

Normalmente, en escenarios de integración de datos deberá crear o actualizar los datos en Dataverse desde otros orígenes. Dataverse puede tener ya registros con el mismo identificador único, que puede ser una clave alternativa. Si existe una fila de la tabla, desea actualizarla. Si no existe, debe crearlo para sincronizar los datos que se agregan con los datos de origen. Este es el escenario cuando hay que usar upsert.

El siguiente ejemplo usa UpsertRequest dos veces. La primera vez que se crea la fila de la cuenta y la segunda vez que se actualiza porque tiene un valor accountnumber y hay un clave alternativa usando esa columna (attrbute).

Para ambas llamadas, la propiedad UpsertResponse.RecordCreated indica si la operación creó una fila o no.

// This environment has an alternate key set for the accountnumber attribute.

//Instantiate account entity with accountnumber value
var account = new Entity("account", "accountnumber", "0003");
account["name"] = "New Account";

//Use Upsert the first time
UpsertRequest request1 = new UpsertRequest() {
Target = account
};

//The new entity is created
var response1 = (UpsertResponse)svc.Execute(request1);
Console.WriteLine("Record Created: {0}",response1.RecordCreated); //true

//Update the name of the existing account entity
account["name"] = "Updated Account";

//Use Upsert for the second time
UpsertRequest request2 = new UpsertRequest()
{
Target = account
};

//The existing entity is updated.
var response2 = (UpsertResponse)svc.Execute(request2);
Console.WriteLine("Record Created: {0}", response2.RecordCreated); //false

Más información: Uso de Upsert para insertar o actualizar un registro

Delete

El método IOrganizationService.Delete simplemente requiere el nombre lógico de la tabla y el identificador único. Independientemente de si usa la clase Entidad de enlace en tiempo de ejecución o una clase de entidad generada de enlace de tiempo de compilación, puede usar la siguiente sintaxis para eliminar una operación si pasa las propiedades Entity.LogicalName y Entity.Id.

svc.Delete(retrievedEntity.LogicalName, retrievedEntity.Id);

O bien, puede los valores:

svc.Delete("account", new Guid("e5fa5509-2582-e811-a95e-000d3af40ae7"));

Importante

Las operaciones de eliminación pueden iniciar operaciones en cascada que pueden eliminar filas secundarias para mantener la integridad de los datos según la lógica definida para Relaciones en el entorno. Más información: Comportamiento de las relaciones de tabla

Uso de la clase DeleteRequest

Puede usar la clase DeleteRequest en lugar del método IOrganizationService.Delete, pero solo es necesario cuando desea especificar un comportamiento de concurrencia optimista.

var retrievedEntity = new Entity("account")
{
    Id = new Guid("c81ffd82-cd82-e811-a95c-000d3af49bf8"),
    RowVersion = "986335"

};

var request = new DeleteRequest()
{
    Target = retrievedEntity.ToEntityReference(),
    ConcurrencyBehavior = ConcurrencyBehavior.IfRowVersionMatches
};

svc.Execute(request);

Comportamiento de la simultaneidad optimista

Puede especificar el comportamiento de la simultaneidad optimista de la operación configurando la propiedad ConcurrencyBehavior de las clases UpdateRequest o DeleteRequest.

La lógica para actualizar o eliminar la fila puede basarse en datos obsoletos. Si los datos actuales son diferentes porque han cambiado desde que se recuperaron, la simultaneidad optimista proporciona una forma de cancelar una operación de actualizar o eliminar por lo que es posible que la recupera de nuevo y use los datos actuales para determinar si proseguir.

Para determinar si se ha cambiado la fila, no es necesario comparar todos los valores, puede utilizar la propiedad RowVersion para ver si ha cambiado.

El siguiente ejemplo saldrá bien solamente cuando:

Si RowVersion no coincide, se producirá un error con el mensaje The version of the existing record doesn't match the RowVersion property provided..

var retrievedAccount = new Account()
{   
    Id = new Guid("a976763a-ba1c-e811-a954-000d3af451d6"), 
    RowVersion = "986323" 
};

var account = new Account();
account.Id = retrievedAccount.Id;
account.RowVersion = retrievedAccount.RowVersion;

// set attribute values
account.CreditOnHold = true;

//Update the account
var request = new UpdateRequest()
{ 
    Target = account,
    ConcurrencyBehavior = ConcurrencyBehavior.IfRowVersionMatches 
};

try
{
    svc.Execute(request);
}
catch (FaultException<OrganizationServiceFault> ex)
{
    switch (ex.Detail.ErrorCode)
    {
        case -2147088254: // ConcurrencyVersionMismatch 
        case -2147088253: // OptimisticConcurrencyNotEnabled 
            throw new InvalidOperationException(ex.Detail.Message);
        case -2147088243: // ConcurrencyVersionNotProvided
            throw new ArgumentNullException(ex.Detail.Message);
        default:
            throw ex;
    }
}

Más información:

Mensajes de actualización heredados

Hay varios mensajes especializados obsoletos que realizan operaciones de actualización. En versiones anteriores, se requería usar estos mensajes, pero ahora se deben realizar las mismas operaciones usando IOrganizationService.Update o la clase UpdateRequest con el método IOrganizationService.Execute.

Solicitud de mensaje obsoleta Atributo(s) para actualizar
AssignRequest <entidad>.OwnerId
SetStateRequest <entidad>.StateCode
<entidad>.StatusCode
SetParentSystemUserRequest SystemUser.ParentSystemUserId
SetParentTeamRequest Team.BusinessUnitId
SetParentBusinessUnitRequest BusinessUnit.ParentBusinessUnitId
SetBusinessEquipmentRequest Equipment.BusinessUnitId
SetBusinessSystemUserRequest SystemUser.BusinessUnitId

<entidad> hace referencia a cualquier entidad que proporcione este atributo.

Importante

Cuando actualice la columna StateCode, es importante establecer siempre el StatusCode deseado.

StateCode y StatusCode tienen valores dependientes. Puede haber varios valores StatusCode válidos para un valor StateCode dado, pero cada columna de StateCode tiene un único valor DefaultStatus configurado. Cuando actualice StateCode sin especificar un StatusCode, el sistema establecerá el valor de estado predeterminado.

Además, cuando la auditoría está habilitada en la tabla y la columna StatusCode, el valor modificado para la columna StatusCode no se capturará en los datos de auditoría a menos que se especifique en la operación de actualización.

Más información: Comportamiento de operaciones de actualización especializadas

Consulte también

Crear filas de tabla con SDK para .NET
Recuperar una fila de tabla usando SDK para .NET
Asociar y anular la asociación de filas de tabla mediante la SDK para .NET

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