Ver Mensaje Individual
  #1  
Antiguo 25-05-2016
Avatar de Arsenio
Arsenio Arsenio is offline
Miembro
 
Registrado: Oct 2006
Posts: 13
Reputación: 0
Arsenio Va por buen camino
Verificar si hay cambios en Datasets

En muchas ocasiones uso tablas de memoria (sobre todo las KbmMemTable) en conjunto con SQLDirect para trabajar con datos en memoria y en algún momento grabar los cambios generados en la base de datos, esa parte es facil, ambos son TDataSet, pero ¿que ocurre si la tabla tiene miles de registros y realmente no hubo ningún cambio en los datos? Con un "changed" no es suficiente porque eso cambia cuando uno entra a editar un registro, aunque realmente no cambie nada.

Para eso hice un método, que por más que recorre todos los Fields de la tabla y podría parecer lento, siempre es más rápido que ejecutar updates en la base, sobre todo si la base de datos es remota.

En el uses hay que agregar variants y DB.

Código Delphi [-]
class function TFunciones.HayCambiosQueRegistrar(qryOrigen, qryDestino: TDataSet; Modificar: boolean): Boolean;
var
  i: Integer;
  NombreCampo: String;
  rescmp: TVariantRelationship;
begin
  Result := False;
  for i := 0 to qryOrigen.FieldCount - 1 do
  begin
    NombreCampo := qryOrigen.Fields[i].FieldName;
    if (qryDestino.FindField(NombreCampo) <> nil) then
    begin
      rescmp := VarCompareValue(qryOrigen[NombreCampo], qryDestino[NombreCampo]);
      if (rescmp = vrNotEqual) or (not (rescmp = vrEqual)) then
      begin
        Result := True;
        //Si no hay que modificar directamente devuelvo true y sale del loop
        if not Modificar then
        begin
          Break;
        end
        else begin
          if not (qryDestino.State in [dsEdit, dsInsert]) then
            qryDestino.Edit;
          qryDestino[NombreCampo] := qryOrigen[NombreCampo];
        end;
      end;
    end;
  end;
end;

Para usarlo lo que hago es recorrer los registros de la tabla orígen y buscar si existe el registro en el destino, si existe chequea si hay cambios, si hay alguno edita el destino. Si no existe agrega el registro.

Código Delphi [-]
  TablaDetalle.First;
  while not TablaDetalle.EOF do
  begin
    if qryDetalle.Locate('ID', TablaDetalle.FieldByName('ID').AsInteger, []) then
    begin
      if TFunciones.HayCambiosQueRegistrar(TablaDetalle, qryDetalleRecepcion, False) then
      begin
        qryDetalle.Edit;
        TFunciones.CopiarRegistroActual(TablaDetalle, qryDetalleRecepcion);
        qryDetalle.Post;
      end;
    end
    else
    begin
      qryDetalle.Append;
      TFunciones.CopiarRegistroActual(TablaDetalle, qryDetalleRecepcion);
      qryDetalle.Post;
    end;    

    TablaDetalle.Next;
  end;
  
  //Y llamo al método que graba dentro de una transacción y usando ApplyUpdates
  ModuloDatos.GrabarEnTransaccion(qryDetalle);

En realidad, el código anterior no lo tengo igual, ya que el último parámetro realmente lo tengo en True, para que modifique la query si hay cambios, por lo que lo llamo así:

Código Delphi [-]
  if TFunciones.HayCambiosQueRegistrar(TablaDetalle, qryDetalleRecepcion, True) then
  begin
    qryDetalle.Post;
  end;

Espero que les sirva, cualquier duda me pueden consultar...
__________________
Arsenio Lupín - howtoarsenio.blogspot.com
Responder Con Cita