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 cómo se usa la clase Entity generada para crear una cuenta usando 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.
- Cuando quiere que se apliquen reglas de detección de duplicados. Más información: Detectar datos duplicados usando SDK para .NET
- Cuando crea una fila de tabla que representa un componente de la solución, como WebResource, y desea asociarlo con una solución específica. En este caso, incluiría el valor de Solution.UniqueName con el parámetro
SolutionUniqueName
. Más información: Usar mensajes con SDK para .NET
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 manera más eficaz de actualizar varios registros en una sola solicitud. Más información: Operaciones masivas con mensajes
Actualización de entidades relacionadas en una operación
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:
RowVersion
de la fila en la base de datos es igual a986323
- La tabla cuenta está habilitada para la simultaneidad optimista (propiedad EntityMetadata.IsOptimisticConcurrencyEnabled es
true
) - La propiedad
RowVersion
se establece en la fila pasada con la solicitud.
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