[RESUELTO] Borrar registros en un ClientDataSet
#1
Escrito 08 febrero 2010 - 12:30
Estoy trabajando com un ClientDataSet donde agrego registros 'temporales' para que al terminar de agregar los registros que requiero hacer algunos procesos definitivos.
Hasta aquí todo funciona a la perfección, el detalle que se me presenta en este momento es que necesito borrar algunos registros (por X causa), esto lo puedo hacer asignando la propiedad Multiselect del dbgrid y presionando Ctrl+Del, sin embargo, quiero hacer esto desde Delphi.
Los registros a borrar cuentan con un campo igual, por ejemplo, todos los registros que en su campo Descripción sea igual a 'COMEDOR'.
Espero que haya sido claro
Salud OS
#2
Escrito 08 febrero 2010 - 02:44
Por ejemplo, si creamos un ClientDataSet como este:
var tbPrueba: TClientDataSet; // Esta es una variable global // Es una simple tabla con un solo campo "Codigo" que llenamos con los valores del 1 al 1000. var i: Integer; begin tbPrueba:= TClientDataSet.Create(Self); tbPrueba.FieldDefs.Add('Codigo', ftInteger, 0, FALSE); tbPrueba.CreateDataset; for i:= 0 to 1000 do begin tbPrueba.Insert; tbPrueba.FieldValues['Codigo']:= i; tbPrueba.Post; end; tbPrueba.IndexFieldNames:= 'Codigo'; dtsMain.DataSet:= tbPrueba; end;
Y queremos borrar todas los registros con el campo "Codigo" menor de 10, podemos hacer esto:
begin tbPrueba.Filter:= 'Codigo < 10'; tbPrueba.Filtered:= TRUE; tbPrueba.First; while not tbPrueba.Eof do tbPrueba.Delete; tbPrueba.Filtered:= FALSE; end;
No es muy elegante pero es lo que hay .
Y si quieres aumentar el rendimiento yo primero rompería cualquier vinculo entre el ClientDataSet y un DataSource, y después del borrado lo volvería a restaurar. Algo Así:
begin // dtsMain es un DataSource dtsMain.DataSet:= nil; try tbPrueba.Filter:= 'Codigo < 10'; tbPrueba.Filtered:= TRUE; tbPrueba.First; while not tbPrueba.Eof do tbPrueba.Delete; tbPrueba.Filtered:= FALSE; finally dtsMain.DataSet:= tbPrueba; end; end;
#3
Escrito 08 febrero 2010 - 03:18
tbPrueba.DisableControls;
Pero veo que tu aconsejas este:
dtsMain.DataSet:= nil;
hay alguna diferencia?
#4
Escrito 08 febrero 2010 - 03:43
ClientDataSet.First; while not ClientDataSet.EOF do begin if ClientDataSet.FieldByName('campo').AsString='COMEDOR' then ClientDataSet.Delete; ClientDataSet.next; end
El ClientDataSet tiene la propiedad CommandText para hacer consultas solo te permite los Select cuando lo tienes relacionado con otro DataSet y su Provider, modificación a al BD con insert, delete, update no se puede, debes hacerlo como si estuvieses trabajando con los componentes Table.
Saluditos
#5
Escrito 08 febrero 2010 - 03:50
Amigo Seoane, una pregunta, yo acostumbro a realizar esto:
delphi
tbPrueba.DisableControls;
Pero veo que tu aconsejas este:
delphi
dtsMain.DataSet:= nil;
hay alguna diferencia?
Si hay diferencía, asignándole a nil estamos quitando la relación entre el DataSet y el DataSource en cuestión osea que los componentes que estaban mostrando los datos (dbgrids, dbedit....), ya no van a mostrar nada, quedan en blanco y al asignarlo nuevamente volvemos a ver los datos, mientras con DisableControl no sucede eso, solo añadir de utilizar Bokmarks acompañado de DisableControl.
Saluditos
#6
Escrito 08 febrero 2010 - 04:05
hay alguna diferencia?
Pues la respuesta es muy parecida a la del ultimo hilo en que me lo preguntaste. Allí te conteste que no usaba DisableControls por desconocimiento, pero en este caso no lo use porque ya me había olvidado
Soy novato en esto de las bases de datos, rejillas, etc ... así que perdonarme si meto la pata :$
#7
Escrito 08 febrero 2010 - 06:18
Muchas gracias por responder, yo había hecho eso mismo que me comentan y que es recorrer el dataset y borrar el registro que coincida con el argumento dado, el detalle (que no problema) es que yo hago algunos calculos en el evento AfterDelete, entonces aquí viene el primer detalle feo, ese evento recorre el dataset y 'rompe' de alguna forma el while not eof del dataset, hice una chapuza que funciona, pero me parece que es muy lento el proceso y se nota mucho como va borrando registro por registro.
Por eso pense en utilizar la propiedad Multiselect del DBGrid, seleccionar todos los registros que coincidan con el argumento dado y hacer un delete que es lo que hace el Ctrl+Del en el dbgrid y borra todo lo seleccionado.
Seguiré intentando algunas ideas que tengo a ver si puedo lograr mi Caprichito
Salud OS
PD; un gusto verte amiguita Caro, felicidades por el nombramiento en Club Delphi.
#8
Escrito 08 febrero 2010 - 07:07
Pues ya encontré la solución a mi caprichito
procedure Tform1.Button1Click(Sender: TObject); begin DBGrid1.DataSource.DataSet.DisableControls; DBGrid1.DataSource.DataSet.First; while not DBGrid1.DataSource.DataSet.Eof do begin if DBGrid1.DataSource.DataSet['MARCA'] = 'ALTIMA 2003' then DBGrid1.SelectedRows.CurrentRowSelected := True; DBGrid1.DataSource.DataSet.Next; end; DBGrid1.DataSource.DataSet.EnableControls; DBGrid1.SelectedRows.Delete; end;
Doy por [RESUELTO] este hilo, sin embargo, quedo abierto a otras posibilidades
Salud OS
#9
Escrito 09 febrero 2010 - 07:12
hay alguna diferencia?
Pues la respuesta es muy parecida a la del ultimo hilo en que me lo preguntaste. Allí te conteste que no usaba DisableControls por desconocimiento, pero en este caso no lo use porque ya me había olvidado
Soy novato en esto de las bases de datos, rejillas, etc ... así que perdonarme si meto la pata :$
jajaja en serio ya te lo había preguntado jajajaja, que mala memoria... ups, disculpa.
#10
Escrito 09 febrero 2010 - 07:21
var Temp: TDataSetNotifyEvent; begin Temp:= ClientDataSet1.AfterDelete; ClientDataSet1.AfterDelete:= nil; try // Aqui recorres el dataset borrando, con el metodo que prefieras finally ClientDataSet1.AfterDelete:= Temp; // Y aqui lo llamamos por si necesitas recalcular ClientDataSet1.AfterDelete(ClientDataSet1) end; end;
#11
Escrito 09 febrero 2010 - 10:04
Si el problema es el evento AfterDelete, no hay problema
Por eso amo a Delphi, todo se puede y lo que no se inventa, esa es otra forma de ver el asunto amigo seoane, pero fijate que con la alternativa de borrar los registros seleccionados se ejecuta solo una vez el evento AfterDelete que es lo que yo me aferré a hacer
De cualquier forma es interesante el asunto de ejecutar un evento X al gusto o necesidad en tiempo de ejecución , siempre es bueno tener alternativas disponibles
Salud OS
#12
Escrito 09 febrero 2010 - 01:56
... pero fijate que con la alternativa de borrar los registros seleccionados se ejecuta solo una vez el evento ...
No estoy seguro de eso. Si te fijas en el código del "Delete" del DBGrid, lo único que hace, si hay seleccionados varios registros, es recorrer las lista de Bookmarks donde están guardados esos registros y borrarlos usando el método "Delete" del DataSet.
Lo que yo creo es que ejecuta el método AfterDelete tantas veces como registros tengas seleccionados, pero como no recorre el Dataset registro a registro, sino que se dirige directamente a cada registro usando los Bookmarks, da igual que en el método AfterDelete te andes moviendo por los registros del DataSet
PD: Mira que me gustas darle vueltas a las cosas
#13
Escrito 09 febrero 2010 - 01:59
... pero fijate que con la alternativa de borrar los registros seleccionados se ejecuta solo una vez el evento ...
No estoy seguro de eso. Si te fijas en el código del "Delete" del DBGrid, lo único que hace, si hay seleccionados varios registros, es recorrer las lista de Bookmarks donde están guardados esos registros y borrarlos usando el método "Delete" del DataSet.
Lo que yo creo es que ejecuta el método AfterDelete tantas veces como registros tengas seleccionados, pero como no recorre el Dataset registro a registro, sino que se dirige directamente a cada registro usando los Bookmarks, da igual que en el método AfterDelete te andes moviendo por los registros del DataSet
PD: Mira que me gustas darle vueltas a las cosas
Ah caray, vas a hacer que haga un debug a mi código para verificar lo que dices, no es que dude de tus palabras pero pues quiero estar seguro
Salud OS
#14
Escrito 09 febrero 2010 - 07:51
Honor a quien honor merece
Salud OS
#15
Escrito 10 febrero 2010 - 05:36