Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 03-08-2018
marco3k marco3k is offline
Miembro
 
Registrado: feb 2015
Posts: 60
Poder: 10
marco3k Va por buen camino
Actualizar varias filas en un ClientDataSet desconectado.

Hola, tengo una duda respecto al manejo de ClientDataSet, quisiera saber si hay alguna manera de actualizar varios registros en un ClientDataset que trabaja en modo desconectado. Lo que hice es obtener los datos de una BD Firebird con componentes IBX en un ClientDataSet y ahi hago mis operaciones para sacar reportes.
Hay un campo que se llama seleccion el cual el usuario hace click y selecciones que mes quiere imprimir el código que asi:
Código Delphi [-]
procedure TLogicaBoletaPago.VerBoleta;
var var_cod_boleta_tmp,var_cod_boleta : string;
begin
  if TListaBoletaTmp.RecordCount>0 then
  begin
    TListado.Filter := '';
    TListado.Filtered := True;
    repeat
      TListado.Edit;
      TListado.FieldByName('SELECCION').AsInteger := 0;
      TListado.Post;
      TListado.Next;
    until TListado.Eof;
    TListado.First;
    //***
    TListaBoletaTmp.First;
    while TListaBoletaTmp.Eof = False do
    begin
      if TListaBoletaTmp.FieldByName('SELECCION').Value=True then
      begin
        var_cod_boleta_tmp := TListaBoletaTmp.FieldByName('anio').AsString +
        TListaBoletaTmp.FieldByName('mes').AsString +
        TListaBoletaTmp.FieldByName('mes_sup').AsString +
        TListaBoletaTmp.FieldByName('dni').AsString +
        TListaBoletaTmp.FieldByName('tipo_pla').AsString +
        TListaBoletaTmp.FieldByName('nro_bol').AsString;
        TListado.RecordCount;
        TListado.First;
        while TListado.Eof = False do
        begin
          var_cod_boleta := TListado.FieldByName('anio').AsString +
          TListado.FieldByName('mes').AsString +
          TListado.FieldByName('mes_sup').AsString +
          trim(TListado.FieldByName('dni').AsString) +
          TListado.FieldByName('tipo_pla').AsString +
          TListado.FieldByName('nro_bol').AsString;
          if var_cod_boleta_tmp = var_cod_boleta then
          begin
            TListado.Edit;
            TListado.FieldByName('SELECCION').AsInteger := 1;
            TListado.Post;
          end;
          TListado.Next;
        end;
      end;
      TListaBoletaTmp.Next;
    end;
  end;
  TListaBoletaTmp.First;
  TListado.Filter := '[seleccion] = 1';
  TListado.Filtered := True;
end;
El código anterior funciona bien, pero cuando hay varios registros se ejecuta un poco lento. Es ahi donde viene mi duda si hay un comando a lo Visual Foxpro "REPLACE ALL".
Aca tengo la versión en Visual Foxpro del codigo Delphi anterior:
Código:
    IF USED("cur_bol")
        SELECT cur_bol
        SET FILTER TO 
        REPLACE ALL seleccion WITH 0
        GO TOP 
        SELECT cur_boleta_rep
        GO TOP
        SCAN FOR cur_boleta_rep.seleccion = .T.
            SELECT cur_bol
            REPLACE ALL cur_bol.seleccion WITH 1 FOR cur_bol.anio + cur_bol.mes + cur_bol.mes_sup + ALLTRIM(cur_bol.dni) + cur_bol.tipo_pla + ALLTRIM(cur_bol.nro_bol) =;
            cur_boleta_rep.anio + cur_boleta_rep.mes + cur_boleta_rep.mes_sup + ALLTRIM(cur_boleta_rep.dni) + cur_boleta_rep.tipo_pla + ALLTRIM(cur_boleta_rep.nro_bol)    
        ENDSCAN 
        SELECT cur_bol
        SET FILTER TO seleccion = 1
        COUNT TO var_filas
        GO TOP 
    ENDIF
Como se puede apreciar la version de Visual Foxpro tiene menos código, hace lo mismo que el código delphi y mas rápido, ya que si hay varios registros sigue ejecutandose rápido y tambien se conecta a la misma BD Firebird con conexion ODBC, obtiene los datos en un cursor y ahi saco los reportes.


Visual FoxPro tiene un comando que es REPLACE y con parametro ALL me reemplaza varios registros a la vez, en cambio en delphi tengo que hacer 3 bucles para actualizar datos:
1. Para poner 0(cero) al campo seleccion del ClientDataSet temporal
2. para recorrer los periodos seleccionados
3. para poner 1(uno) en el ClientDataSet donde estan las boletas de pago.


Por eso la duda es si hay algun comando "REPLACE" en Delphi que me permita ejecutar mas rápido mi rutina.
Agradesco de antemano si me pudieran ayudar, ya que aun no he logrado ejecutar mas rápido mi código delphi.


PD: Uso Delphi 7.

Última edición por ecfisa fecha: 03-08-2018 a las 03:29:09. Razón: ajustar código foxpro
Responder Con Cita
  #2  
Antiguo 03-08-2018
marco3k marco3k is offline
Miembro
 
Registrado: feb 2015
Posts: 60
Poder: 10
marco3k Va por buen camino
Actualizar varias filas en un ClientDataSet desconectado.

Hola compañeros, despues de analizar una recomendacion en este foro que hizo Al Gonzáles en este Hilo "clubdelphi.com/foros/showthread.php?t=85143&page=2" y cambie la propiedad LogChanges a False del ClientDataSet. Tambien cambie el acceso a los campos como indica el compañero Mick en este Hilo "clubdelphi.com/foros/showthread.php?t=21764".

Hice los cambios respectivos y la velocidad de ejecución de la rutina en Delphi bajo de 15 segundos a 3 segundos. El código quedo asi:

Código Delphi [-]
procedure TLogicaBoletaPago.VerBoleta;
var var_cod_boleta_tmp,var_cod_boleta : string;
begin
  if TListaBoletaTmp.RecordCount>0 then
  begin
    TListado.LogChanges := False; //cambio 1
    TListado.Filter := '';
    TListado.Filtered := False;
    TListado.First;
    repeat
      TListado.Edit;
      TListadoSELECCION.Value := 0; //El acceso directo a campos, cambio 2
      TListado.Post;
      TListado.Next;
    until TListado.Eof;
    TListado.First;
    //***
    TListaBoletaTmp.First;
    while TListaBoletaTmp.Eof = False do
    begin
      if TListaBoletaTmpSELECCION.Value=True then
      begin
        var_cod_boleta_tmp := TListaBoletaTmpANIO.Value +
        TListaBoletaTmpMES.Value +
        TListaBoletaTmpMES_SUP.Value +
        TListaBoletaTmpDNI.Value +
        TListaBoletaTmpTIPO_PLA.Value +
        TListaBoletaTmpNRO_BOL.Value;
        TListado.First;
        while TListado.Eof = False do
        begin
          var_cod_boleta := TListadoANIO.Value +
          TListadoMES.Value +
          TListadoMES_SUP.Value +
          trim(TListadoDNI.Value) +
          TListadoTIPO_PLA.Value +
          TListadoNRO_BOL.Value;
          if var_cod_boleta_tmp = var_cod_boleta then
          begin
            TListado.Edit;
            TListadoSELECCION.Value := 1;
            TListado.Post;
          end;
          TListado.Next;
        end;
      end;
      TListaBoletaTmp.Next;
    end;
  end;
  TListaBoletaTmp.First;
  TListado.Filter := '[seleccion] = 1';
  TListado.Filtered := True;
end;
Aun asi la version de Visual FoxPro con muchos registros se demora 1 seg a lo mucho, si son pocos registros es milisegundos.
Hay algo que menciono Al Gonzáles mencionó en el Hilo que comente lineas arriba:
Cita:
...agregar los registros mediante llamadas de bajo nivel a las interfaces DSBase y DSCursor que contiene el objeto, es decir, ejecutando directamente rutinas de MIDAS. Con ello te ahorras un montón de trámites que la clase hereda de TDataSet.
Tendras Al Gonzáles o algún miembro de este foro algún ejemplo de como ejecutar rutinas MIDAS para reducir a 1 seg la ejecución de la rutina. O alguna otra recomendación que me pudieran brindar y por lo que busque no hay nada equivalente a "REPLACE ALL WITH 0" en Delphi.

Gracias de antemano si me pudieran brindar alguna ayuda.


PD: No puedo agredar hipervínculos asi que puse las direcciones sin el prefijo.
Responder Con Cita
  #3  
Antiguo 04-08-2018
Avatar de movorack
[movorack] movorack is offline
Miguel A. Valero
 
Registrado: feb 2007
Ubicación: Bogotá - Colombia
Posts: 1.346
Poder: 20
movorack Va camino a la famamovorack Va camino a la fama
Un par de interrogantes:

1. ¿Porque concatenas de esa manera los valores y luego haces un ciclo buscando si el valor de cada registro concuerda?, podrías usar un Locate en el segundo dataset con los valores del primero

Código Delphi [-]
if DataSet2.Locate('FIELD1;FIELD2;FIELD3', VarArrayOf([Dataset1Field1.Value, Dataset1Field2.Value, Dataset1Field3.Value]), []) then
begin
  // estableces el filtro
end;

2. ¿Porque realizas el proceso de filtrado de esa manera en lugar de armar el filtro con el valor de los campos del primer dataset?

Código Delphi [-]
Dataset2.Filter := Format('(FIELD1 = %s) and (FIELD2 = %s) and (FIELD3 = %s)', [Dataset1Field1.Value, Dataset1Field2.Value, Dataset1Field3.Value]);
Dataset2.Filtered := True;
__________________
Buena caza y buen remar... http://mivaler.blogspot.com

Última edición por movorack fecha: 04-08-2018 a las 00:38:29.
Responder Con Cita
  #4  
Antiguo 04-08-2018
marco3k marco3k is offline
Miembro
 
Registrado: feb 2015
Posts: 60
Poder: 10
marco3k Va por buen camino
Thumbs up Actualizar varias filas en un ClientDataSet desconectado.

Me respondo yo mismo XD, estuve revisando el código y aplique filtros al ClientDatSet principal TListado y la ejecución mejoró a 1.09 segundos, que ya me parece aceptable. Muestro el codigo final:
Código Delphi [-]
procedure TLogicaBoletaPago.VerBoleta;
var var_cod_boleta_tmp,var_cod_boleta : string;
begin
  if TListaBoletaTmp.RecordCount>0 then
  begin
    TListado.LogChanges := False;
    TListaBoletaTmp.LogChanges := False;
    TListado.Filter := '';
    TListado.Filtered := False;
    TListado.First;
    repeat
      TListado.Edit;
      TListadoSELECCION.Value := 0;
      TListado.Post;
      TListado.Next;
    until TListado.Eof;
    TListado.First;
    //***
    TListaBoletaTmp.First;
    while TListaBoletaTmp.Eof = False do
    begin
      if TListaBoletaTmpSELECCION.Value=True then
      begin
        var_cod_boleta_tmp := TListaBoletaTmpANIO.Value +
        TListaBoletaTmpMES.Value +
        TListaBoletaTmpMES_SUP.Value +
        TListaBoletaTmpDNI.Value +
        TListaBoletaTmpTIPO_PLA.Value +
        TListaBoletaTmpNRO_BOL.Value;
        TListado.First;
        TListado.Filter := '[ANIO] = ' + QuotedStr(TListaBoletaTmpANIO.Value) + ' and [MES] = ' +
        QuotedStr(TListaBoletaTmpMES.Value) + ' and [MES_SUP] = ' + QuotedStr(TListaBoletaTmpMES_SUP.Value) +
        ' and [DNI] = ' + QuotedStr(TListaBoletaTmpDNI.Value);
        TListado.Filtered := True;
        while TListado.Eof = False do
        begin
          var_cod_boleta := TListadoANIO.Value +
          TListadoMES.Value +
          TListadoMES_SUP.Value +
          trim(TListadoDNI.Value) +
          TListadoTIPO_PLA.Value +
          TListadoNRO_BOL.Value;
          if var_cod_boleta_tmp = var_cod_boleta then
          begin
            TListado.Edit;
            TListadoSELECCION.Value := 1;
            TListado.Post;
          end;
          TListado.Next;
        end;
      end;
      TListaBoletaTmp.Next;
    end;
  end;
  TListaBoletaTmp.First;
  TListado.Filter := '[seleccion] = 1';
  TListado.Filtered := True;
end;


Resumiendo si alguien quiere actualizar varias filas en un ClientDataSet desconectado, debe tener en cuenta lo siguiente:


1.- Aplicar la propiedad LogChanges := False del ClientDataset.
2.- Acceder directamente a los campos y no usar FieldByName("TuCampo").
3.- Aplicar Filtros en ves de condiciones al ClientDataSet ya que esto acelera mas el proceso en actualizaciones masivas.


Sin mas espero que a alguien mas le pueda servir lo que me paso a mi.
Aunque, aún me queda la duda de como sería con "rutinas de MIDAS".
Saludos y buen fin de semana.
Responder Con Cita
  #5  
Antiguo 04-08-2018
marco3k marco3k is offline
Miembro
 
Registrado: feb 2015
Posts: 60
Poder: 10
marco3k Va por buen camino
Miguel A. Valero, revise mi código en versión Visual FoxPro y si había que aplicar un filtro. Este es el código FoxPro que expuse en el primes post:
Código:
...
       SCAN FOR cur_boleta_rep.seleccion = .T.
            SELECT cur_bol
            REPLACE ALL cur_bol.seleccion WITH 1 FOR cur_bol.anio + cur_bol.mes + cur_bol.mes_sup + ALLTRIM(cur_bol.dni) + cur_bol.tipo_pla + ALLTRIM(cur_bol.nro_bol) =;
            cur_boleta_rep.anio + cur_boleta_rep.mes + cur_boleta_rep.mes_sup + ALLTRIM(cur_boleta_rep.dni) + cur_boleta_rep.tipo_pla + ALLTRIM(cur_boleta_rep.nro_bol)    
        ENDSCAN 

...
En el REPLACE ALL hay un FOR que es un filtro, entonces me faltaba aplicar ESO en Delphi y con eso mejoro la velocidad.

Última edición por marco3k fecha: 04-08-2018 a las 02:45:20. Razón: Código FoxPro
Responder Con Cita
  #6  
Antiguo 04-08-2018
marco3k marco3k is offline
Miembro
 
Registrado: feb 2015
Posts: 60
Poder: 10
marco3k Va por buen camino
Talking

No actualice bien el código final en el post 4 y no puedo editar el mensaje asi que lo coloco aqui:
Código Delphi [-]
...
    TListaBoletaTmp.First;
    while TListaBoletaTmp.Eof = False do
    begin
      if TListaBoletaTmpSELECCION.Value=True then
      begin
        TListado.Filter := '[ANIO] = ' + QuotedStr(TListaBoletaTmpANIO.Value) + ' and [MES] = ' +
        QuotedStr(TListaBoletaTmpMES.Value) + ' and [MES_SUP] = ' + QuotedStr(TListaBoletaTmpMES_SUP.Value) +
        ' and [DNI] = ' + QuotedStr(TListaBoletaTmpDNI.Value);
        TListado.Filtered := True;
        TListado.First;
        while TListado.Eof = False do
        begin
            TListado.Edit;
            TListadoSELECCION.Value := 1;
            TListado.Post;
            TListado.Next;
        end;
      end;
      TListaBoletaTmp.Next;
    end;
...
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Actualizar registros de ClientDataSet oscarac OOP 1 31-01-2018 11:01:00
Actualizar datos al clientdataset escorpionrojo43 Conexión con bases de datos 1 14-08-2013 18:51:02
Actualizar ClientDataSet usando TADOQuery y DataSetProvider Walterio Providers 4 27-11-2012 21:01:00
Problema al actualizar con ClientDataSet con campos calculados LEVV Conexión con bases de datos 5 14-01-2012 00:29:24
Problemas al actualizar campos numéricos con ClientDataSet e IBX PINO72 Conexión con bases de datos 0 17-03-2007 02:37:44


La franja horaria es GMT +2. Ahora son las 16:29:49.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi