Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Conexión con bases de datos (https://www.clubdelphi.com/foros/forumdisplay.php?f=2)
-   -   Como clonar un TIBDataSet ? (https://www.clubdelphi.com/foros/showthread.php?t=44177)

gluglu 30-05-2007 16:29:22

Como clonar un TIBDataSet ?
 
Hola amigos !

He consultado este hilo, pero no me aclaro del todo.

Quiero hacer lo mismo que el compañero AGAG4, buscar en un DataSet 'paralelo' o 'clonado'. Haciendo uso del DisableControls y posterior EnableControls, no me deja el DBGrid que tiene asociado el IBDataSet de idéntica manera que antes de mi búsqueda y operaciones. Al final acaba subiéndome una fila, o al fin de cuentas, con algunos registros 'traspuestos' después de mis operaciones.

Por eso pensé en 'clonar', como aconsejó Neftalí en el hilo arriba indicado, el DataSet que ya había obtenido con anterioridad. No quiero hacer la consulta SQL de nuevo ya que pueden haber cambiado los registros en la base de datos y por lo tanto obtener un Set de Datos diferente.

Como puedo entonces incorporar a un nuevo DataSet exáctamente los registros que se encuentran en otro dataset diferente ?

He probado :
Código Delphi [-]
...
var
  Aux_DataSet : TIBDataSet;
 
begin
 
  Aux_DataSet := TIBDataSet.Create(Self);
  Aux_DataSet.DataBase    := DM0.IBDatabase1;
  Aux_DataSet.Transaction := DM0.IBTransaction1;
pero cuando Neftalí se refería en su hilo a asociar la misma consulta, no sé como interpretarlo.

Otra opción que no sé como realizarla sería algo así como 'Insertar' en un nuevo DataSet los registros que pueda obtener del DataSet original.

Gracias de nuevo por vuestras ayudas.

ramiretor 31-05-2007 17:20:36

Hola:
Para poder copiar los registros de un DataSet, puedes usar un ClientDataSet que te va a permitir insertarle todos los registros que necesites.

Saludos

gluglu 31-05-2007 18:03:57

Pero entiendo que tendría que recorrer todos los datos de mi IBDataSet original, e ir insertando los registros en el nuevo ClientDataSet, no ?

Es precisamente lo que en teoría no quiero, tener que mover el puntero del IBDataSet original.

ramiretor 31-05-2007 19:22:06

Sí lo que quieres es no moverte del registro actual, puedes usar un bookmark
con eso aseguras moverte, pero regresar a donde estabas originalmente que no?

Saludos

Lepe 31-05-2007 19:35:50

¿Para qué quieres clonar el dataset? ¿vas a realizar alguna búsqueda? ¿quizás comprobar que un dato no se repita?

Saludos

gluglu 31-05-2007 19:48:09

Es un poco complicado explicar por qué no me funciona como yo quiero.

Estoy haciendo un gestor de correo electrónico en mi propia aplicación. Recibo correos, y los muestro en un DBGrid. Logro hacer un Multiselect propio ya que el que viene con el propio TDBGrid no me convence para mis preferencias.

Cuando hago un multiselect con Shift - Click del ratón, hago un DisableControls y posterior EnableControls del DBGrid. También guardo el Bookmark en una variable privada. Para que sea funcional el Shift - Click, necesito moverme dentro del DataSet para ver 'primeros' y 'ultimos' registros marcados, para después volver a completar una lista propia (con una numeración propia interna) que me lleva la lista de los registros marcados.

Al recorrer el DataSet, aun con el DisableControls activado, y terminar de llenar mi lista de marcados con los registros correspondientes, intento volverl a la misma e idéntica situación del Grid que había antes del DisableControls. Aun utilizando el Bookmark correspondiente, al final resulta que como no puedo saber cual era el primer registro que se mosrtaba en la primera línea visible del DBGrid, y al volver al registro original mediante el Bookmark correspondiente, el DBGrid al final hace lo que quiere y puede o no subirme o bajarme una o varias líneas de las que originalmente se mostraban.

Efecto desagradable para el usuario. Si pulsa Shift - Click los registros marcados no están donde está el cursor del ratón y es un poco desconcertante.

Solución que pensé, clonar el DataSet, y completar mi lista de seleccionados con los números internos que contenga el DataSet clonado, y de esta manera no mover el puntero de mi DBGrid original, y con un Repaint conseguir el efecto de marcado de todos los registros que habré seleccionado en el DataSet clonado.

Espero haberme explicado correctamente. No sé de qué otra manera hacerlo con el DBGrid propio del Delphi. Descartado utilizar componentes de terceros.

A lo mejor me dais otros consejos diferentes.

Gracias a todos. ;)

Angel Fernández 25-10-2008 19:53:04

También quisiera saber como clonar un IbDataSet
 
Reflotando este hilo de gluglu de hace ya más de un año, quisiera saber si lograste resolver el problema de la clonación y cómo lo hiciste porque yo ahora me encuentro en la misma situación.

En mi caso es un fibdataset pero supongo que será igual que un ibdataset. Quiero tener dos dbgrid que reciben datos de dos fibdataset distintos pero con el mismo sql, misma tabla,etc. Es decir el ds2 es un clon del ds1. Lo que quiero hacer es poder filtrar el ds2 de forma independiente al ds1 y así, en un dbgrid mostrar todos los datos de una consulta, y en el segundo dbgrid los datos filtrados.

Recorrer los datos del ds1 no me sirve por lentitud y asignar todas los propiedades del ds1 al ds2 incluída la consulta en sql y volverla a abrir es también muy lento.

¿Alguna solución?

Un saludo.

Al González 26-10-2008 04:40:36

Respondiendo a Ángel. Yendo desde lo más básico, podrías averiguar si el componente FIBDataSet cuenta con un método llamado Clone, CloneCursor o algún otro por el estilo, como es el caso en ciertos tipos de componentes de acceso a datos, y entonces ver su ayuda y probarlo para ver si te funciona como esperas.

Ahora bien, si lo anterior no fuese factible y continuase tu justa indisposición a ejecutar de nuevo la consulta sobre el servidor con otro componente (por la lentitud que mencionas), existe la alternativa sugerida arriba por ramiretor de usar componentes TClientDataSet. Una de las ventajas de esta clase de objeto es que posee un método llamado AppendData con el cual puedes copiar el contenido de un conjunto de datos dentro de otro, sin tener que realizar ninguna nueva consulta al servidor ni recorrer manualmente cada uno de los registros originales.

Si lo analizas, hacer dos veces la consulta sobre el servidor es lo que más vale la pena tratar de evitar, pero el copiar las propiedades de un componente a otro puede que no pase de escribir unas cuantas líneas.

En caso de que aún esto último quisieras evitar, y trabajes con Delphi 7, podrías emplear la función ghCloneDataSet de GH Freebrary (sin pretender hacer spam). Esta función no clona los registros contenidos en el conjunto de datos, pero sí se encarga de crear un nuevo componente con todas y cada una de las propiedades y eventos establecidos en el original, además de sus parámetros e incluso campos persistentes que le hayas establecido en tiempo de diseño (con la opción de excluir algunos de estos elementos).

Código Delphi [-]
Uses
  GHFData;

// Ejemplo con TIBDataSet
procedure TForm1.Button1Click(Sender: TObject);
begin
  { Clonamos el conjunto de datos IBDataSet1, haciendo que el formulario
    sea el dueño del nuevo componente y asignando éste a DataSource2 }
  DataSource2.DataSet := ghCloneDataSet (IBDataSet1, Self, 'Active;Name');

  { Abrimos el conjunto de datos clon, apertura con la cual se ejecuta una
    consulta más sobre el servidor }
  DataSource2.DataSet.Open;
end;

// Ejemplo con TClientDataSet
procedure TForm1.Button2Click(Sender: TObject);
begin
  { Clonamos el conjunto de datos ClientDataSet1, haciendo que el
    formulario sea el dueño del nuevo componente y asignando éste a
    DataSource2 }
  DataSource2.DataSet := ghCloneDataSet (
    ClientDataSet1, Self, 'Active;Name');

  { Asignamos (agregamos) al conjunto de datos clon una copia de los
    registros actuales de ClientDataSet1 (sin necesidad de consultar al
    servidor nuevamente) }
  TClientDataSet (DataSource2.DataSet).AppendData (
    ClientDataSet1.Data, True);
end;

NOTA: Dependiendo de cuál sea el actual dueño del conjunto de datos a clonar, convendrá excluir del copiado a la propiedad Name, ya que no es posible tener dos componentes del mismo nombre conferidos al mismo dueño (propietario), a menos, claro, que la propiedad Name de éstos se deje vacía. (El ejemplo lo hice con los conjuntos de datos colocados dentro del formulario).

Un abrazo con copia.

Al. :)

RONPABLO 26-10-2008 07:51:25

Esto se me parece a una necesidad que tuve...

Angel Fernández 26-10-2008 15:09:03

Gracias por vuestra ayuda Ronpablo y Al. Como siempre, el maestro Al siempre da más de lo que uno podría esperar en este foro. Espero algún día saber la mitad que tú.

Un saludo.

Angel Fernández 27-10-2008 19:24:12

Lo he resuelto con el componente kbmMemTable
 
He resuelto el problema con el componente kbmMemTable que es libre para uso no comercial.
Podéis bajarlo de http://www.components4programmers.co...able/index.htm

Se inserta un kbmMemtable y se le asignan las siguientes propiedades:

Código Delphi [-]
MemTable1.LoadFromDataSet(RxDBGrid1.DataSource.DataSet,mtcpoStructure,mtcpoOnlyActiveFields,mtcpoPro  perties,mtcpoLookup,mtcpoCalculated]);
MemTable1.Filter:='Sensor ='+quotedstr('tem025');
MemTable1.Filtered:=true;
MemTable1.Open;
MemTable1.Active:=True;

Luego conectamos un datasource al memtable1 y un dbgrid al datasource y listo.

No es la solución que me sugería Al González; es peor quizá porque implica el uso de componentes de terceros, pero cuando Al me contestó ya estaba casi resuelto y he querido dejar constancia de ello.

Espero le sirva a alguien.

Un saludo.


La franja horaria es GMT +2. Ahora son las 06:24:26.

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