2009-07-08 18 views
5

En el controlador de eventos AfterPost para un ClientDataSet, necesito la información si la función ApplyUpdates para el registro actual hará una actualización o una inserción.¿Cómo puedo detectar si ApplyUpdates insertará o actualizará datos?

El evento AfterPost se ejecutará para los registros nuevos y actualizados, y no quiero declarar una nueva variable Flag para indicar si una operación 'update' o 'insert' está en progreso.

código Ejemplo:

procedure TdmMain.QryTestAfterPost(DataSet: TDataSet); 
begin 
    if IsInserting(QryTest) then 
    // ShowMessage('Inserting')... 
    else 
    // ShowMessage('Updating'); 

    QryTest.ApplyUpdates(-1); 
end; 

La aplicación escribirá un registro en el método AfterPost, después de ApplyUpdate ha completado. Entonces, este método es el que está más cerca de la acción, preferiría una solución que pueda insertarse por completo en este controlador de eventos.

¿Cómo podría implementar la función IsInserting, usando la información de la instancia ClientDataSet QryTest?

Editar: Voy a intentar ClientDataSet.UpdateStatus que se explica here.

+0

¿Qué piensas hacer? ¿Realiza validaciones, actualiza la interfaz de usuario o algo de manipulación de datos? – zendar

+0

La aplicación escribirá un registro en el método AfterPost, después de que se haya completado ApplyUpdate. Entonces, este método es el que está más cerca de la acción, preferiría una solución que pueda insertarse por completo en este controlador de eventos. Comprobar la matriz Delta aquí parece ser la forma más fácil. – mjn

+0

Este es el mejor lugar si se registra por usuario, en el lado del cliente. Si desea el registro central para todos los usuarios, un mejor lugar estaría en el lado del servidor en el evento AfterApplyUpdates en TDataSetProvider. – zendar

Respuesta

5

ApplyUpdates no le da esa información, ya que puede ser Insertar, actualizar y eliminar.

ApplyUpdates aplica la información de cambio almacenada en la matriz Delta. Esa información de cambio puede, por ejemplo, contener cualquier cantidad de cambios de diferentes tipos (inserciones, eliminaciones y actualizaciones) y todos estos se aplicarán en la misma llamada.

En TDatasetProvider tiene el evento BeforeUpdateRecord (o algo así, dormir hace cosas graciosas en la memoria :-)). Se invoca ese evento antes de que cada registro de Delta se aplique a la base de datos/conjunto de datos subyacente y, por lo tanto, al lugar donde se obtiene dicha información ... Pero Showmessage detendrá el proceso de solicitud.

EDIT: Ahora me acordé de que hay otra opción: se puede asignar a otra propiedad de Delta datos ClientDataSet y leer el conjunto de datos UpdateStatus para ese registro. Por supuesto, es necesario hacer esto antes de ApplyUpdates haciendo ...

var 
    cdsAux: TClientDataset; 
begin 
    . 
    . 
    <creation of cdsAux> 
    cdsAUx.Data := cdsUpdated.Delta; 
    cdsAux.First; 
    case cdsAux.UpdateStatus of 
    usModified: 
     ShowMessage('Modified'); 
    usInserted: 
     ShowMessage('Inserted'); 
    usDeleted: 
     ShowMessage('Deleted'); // For this to work you have to modify 
           // TClientDataset.StatusFilter 
    end; 
    <cleanup code> 
end; 
+0

Esto suena muy bien. Si ApplyUpdate solo está relacionado con un registro, Delta arry solo contendrá una entrada que sabe si se trata de una actualización o una inserción. Entonces solo necesito una forma de acceder a esta información en el Delta. – mjn

+0

¿Por qué usa un segundo CDS? Esperaría que UpdateStatus ya esté disponible en el primer CDS, así que podría leerlo directamente. ¿O es StatusFilter la respuesta por la cual se necesita un segundo? – mjn

+0

Porque con los segundos cds tendrá solo el contenido del Delta, y nada más. Pero es solo una forma alternativa de hacerlo, sin pasar por el proveedor del conjunto de datos. –

4

caso BeforeUpdateRecord en TDataSetProvider se define como:

procedure BeforeUpdateRecord(Sender: TObject; SourceDS: TDataSet; DeltaDS: 
          TCustomClientDataSet; UpdateKind: TUpdateKind; 
          var Applied: Boolean); 

Parámetro UpdateKind dice lo que se hará con el expediente: ukModify, ukInsert or ukDelete . Puede probarlo de esta forma:

procedure TSomeRDM.SomeProviderBeforeUpdateRecord(Sender: TObject; 
     SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind: TUpdateKind; 
     var Applied: Boolean); 
begin 
    case UpdateKind of 
    ukInsert : 
     // Process Insert; 
    ukModify : 
     // Process update 
    ukDelete : 
     // Process Delete 
    end; 
end; 

Nota: este evento es la firma de Delphi 7. No sé si ha cambiado en las últimas versiones de Delphi.

2

Establecer la ClientDataSet.StatusFilter a un valor TUpdateStatus, y después lee ClientDataSet.RecordCount

por ejemplo,

ClientDataSet1.StatusFilter := [usDeleted]; 
ShowMessage(IntToStr(ClientDataSet1.RecordCount)); 

devolverá el número de consultas de eliminación que se ejecutarán.

Tenga en cuenta dos cosas, sin embargo.Establecer StatusFilter en usModified siempre incluye tanto los registros modificados como los no modificados, por lo que toma la mitad de ese valor (un valor de 4 significa que se ejecutarán 2 consultas de actualización). Además, establecer StatusFilter en [] (un conjunto vacío) es cómo restaurar a la vista predeterminada (Modificada, Sin modificar e Insertar)

Asegúrese de que los cambios no publicados se hayan publicado antes de hacerlo, de lo contrario los cambios no publicados no se pueden considerado.

+0

¡Muchas gracias, esta fue la pieza que falta de la solución más fácil! Ver mi comentario en la respuesta de Fabricio Araujo. – mjn

Cuestiones relacionadas