Ver Mensaje Individual
  #1  
Antiguo 30-07-2010
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Reputación: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Combinación fallida de Filter, RevertRecord y UpdateStatus

Hola a todos.

Hace tiempo que no escribía sobre TClientDataSet, una clase nativa sobre la que he trabajado considerablemente y que aún sigue dándome una que otra sorpresa (la mayoría buenas).

Hoy encontré una posible falla en la versión de Delphi 7 de ese componente, la cual me gustaría compartir aquí. Primero que nada para advertir sobre su existencia y proponer un sencillo remedio (work around), pero también para saber si se trata de un defecto conocido y si éste persiste en las nuevas versiones de Delphi.

Con un objeto TClientDataSet nativo que ya se encuentre abierto y ordenado por su campo llave (ID en este ejemplo), hagamos lo siguiente:

Código Delphi [-]
  With CDS1 Do
  Begin
    // Vaciamos la memoria del conjunto de datos
    EmptyDataSet;

    // Agregamos un primer registro en memoria
    Append;
    FieldValues ['ID'] := 10;
    // Aquí otras asignaciones que fueran necesarias
    Post;

    // Agregamos un segundo registro en memoria
    Append;
    FieldValues ['ID'] := 11;
    // Aquí otras asignaciones que fueran necesarias
    Post;

    { Filtramos el conjunto de datos para que solamente el primer registro
      sea visible }
    Filter := 'ID = 10';
    Filtered := True;

    { Si en este punto revisamos la propiedad UpdateStatus, notaremos que
      su valor es usInserted (pues el registro es nuevo y no ha sido
      aplicado a la base de datos) }
    If UpdateStatus = usInserted Then
      ShowMessage ('El registro ' + FieldByName ('ID').AsString +
        ' es nuevo.');

    // Llamamos al método RevertRecord para deshacernos del registro 10
    RevertRecord;

    If Not Locate ('ID', 10, []) Then
      ShowMessage ('Nos deshicimos del registro 10 (el filtro sigue ' +
        'siendo ' + QuotedStr (Filter) + ').');

    { Desactivamos el filtro.  Al hacer esto, el registro 10 (que ya
      habíamos eliminado con RevertRecord) ¡vuelve a aparecer y con
      estado usUnmodified! }
    Filtered := False;
    Filter := '';

    If Locate ('ID', 10, []) And (UpdateStatus = usUnmodified) Then
      ShowMessage ('Quitamos el filtro, y el registro ' +
        FieldByName ('ID').AsString + ' reapareció y como NO nuevo.');
  End;

El remedio que encontré fue casi obvio: usar Delete en lugar de RevertRecord.

La ayuda de Delphi no especifica si el método RevertRecord es aplicable solamente a registros que tienen el estado usModified, o si también puede ser utilizado con los que tienen el estado usInserted. No obstante, parece funcionar muy bien en el segundo caso mientras el conjunto de datos no tenga un filtro activo.

Así pues, mi recomendación sería que se utilice el método Delete en lugar de RevertRecord si se desea eliminar de la lista de cambios a algún registro nuevo (al menos mientras exista el problema planteado). Por otra parte, con los registros traídos de la base de datos y modificados en memoria (estado usModified), no parece haber problema al usar RevertRecord para deshacer sus cambios aunque haya un filtro presente.

Espero sea de ayuda lo anterior, y de antemano gracias por cualquier información relacionada que puedan proporcionar.

Un abrazo irreversible.

Al González.

Última edición por Al González fecha: 30-07-2010 a las 00:55:15.
Responder Con Cita