Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Firebird e Interbase (https://www.clubdelphi.com/foros/forumdisplay.php?f=19)
-   -   IBDataset no guarda registros insertados y editados antes de commit (https://www.clubdelphi.com/foros/showthread.php?t=72267)

Tcmn 07-02-2011 18:28:35

IBDataset no guarda registros insertados y editados antes de commit
 
Hola tengo estoy haciendo un sistema con Delphi 6, Firebird 2.1, Componentes IBX en Windows XP Profesional.

Las tablas no hacen commit/commitretaining ni rollback/rollbackretaining en sus eventos sino que lo manejo con BitBtns para confirmar todos los cambios hechos a las tablas.

Me encontrado con algo curioso. Al insertar registros en la aplicacion cliente y despues modificar esos mismos registros previamente insertados sin hacer commit no me guarde el ultimo valor que puse en cierto campo sino el que puse al momento de insertar. Un ejemplo es el sig:

Inserto un registro:
Código:


Tabla.Insert;
tablaCAmpo1.Value:='ValorAl insertar Campo1';
tablaCAmpo2.Value:='ValorAl insertar Campo2';
tablaCAmpo3.Value:='ValorAl insertar Campo3';
Tabla.Post;

Ese mismo registro lo modifico despues:
Código:


Tabla.Edit;
tablaCAmpo2.Value:='Valor nuevo al Editar Campo2';{Modifico lo que hay en un campo}
Tabla.Post;

Despues hacemos commit:

Código:

Transaccion.Commit;
La logica dice que el Campo2 contiene la cadena "Valor nuevo al Editar Campo2" al registrarse los datos en la base de datos pero resulta que no. Lo que se guarda en la base de datos es lo que haya registrado en los campos al momento de dar de alta el registro, es decir, la cadena: "ValorAl insertar Campo2".

Espero me haya explicado. Esto ocurre con cualquier tabla(IBDataset) que tenga en mi aplicacion.

Nota: Cuando un registro se inserta, hago commit y despues modifico el mismo registro ahora si me registra los cambios que haga a ese registro.

Gracias de antemano por la ayuda que me puedan brindar.

Casimiro Notevi 07-02-2011 20:17:25

Bueno, primero de todo, no deberías de trabajar de esa manera. Después de hacer .post hay que confirmar con commit/commitretaining

Y al hacer esto:
Código Delphi [-]
Tabla.Edit;
TablaCampo2.Value:='Valor nuevo al Editar Campo2';
Tabla.Post;

En teoría, estás editando el primer registro. Deberías posicionarte antes en el registro que vas a editar.

Tcmn 07-02-2011 20:22:21

Lo que pasa es que es un formulario donde al entrar el usuario da de alta un registro como si fuera una factura con varios detalles, por lo que se confirma (Commit) hasta cuando se esta seguro de que procede la alta.

Los registros del detalle se insertan en un DBGrid por lo que a veces se dan de alta 3 o mas detalles y antes de confirmar (Commit) el operario llega a modificar uno de los registros del detalle como la descripcion o el monto.

Gracias por la atencion a este hilo.

Casimiro Notevi 07-02-2011 20:26:33

Debes confirmar justo después de grabar. Si lo van a modificar después tan sólo tienes que buscar ese registro, lo presentas y que lo editen. Al terminar haces de nuevo .post y confirmas.

Tcmn 07-02-2011 20:29:43

Ok. Pense que yo estaba mal en alguna configuracion de los IBX, y pues con eso de que tengo entendido que ya no se esta dando soporte a las actualizaciones de IBX para Firebird, creo que ya me tocara acostumbrar a trabajar asi, porque aparte busque en los foros, google, documentacion y no encontre nada relativo a esto.

Gracias

ecfisa 07-02-2011 20:55:40

Hola.

Más allá de que la práctica aconsejada por Casimiro es la que creo correcta y siempre utilizo, me quedé con la duda...
Probando, encuentro que las líneas de Tcmn, con Delphi 7 e Firebird 2.5 funcionan correctamente.

Mi primera prueba fué con un TIBDataSet y todo correcto, luego pensé que podría ser un problema del TIBTable, componente que no había usado hasta hoy. Pero no, con ambos componentes el código funciona bién.

Usé este código en la prueba:
Código Delphi [-]
procedure TForm1.Button1Click(Sender: TObject);
begin
  with IBDataSet1 do //IBTable1  do
  begin
    Insert;
    FieldByName('RAZON').AsString:= 'INSERTADO';
    FieldByName('CUIT').AsString:= '44444444444';
    FieldByName('DOMICILIO').AsString:= 'CCCCCCCCC';
    Post;
    ShowMessage(' ');
    Edit;
    FieldByName('RAZON').AsString:= 'MODIFICADO';
    FieldByName('CUIT').AsString:= '55555555555';
    FieldByName('DOMICILIO').AsString:= 'DDDDDDDDD';
    Post;
    IBTransaction1.CommitRetaining;
  end;
end;

Si el problema fueran los privilegios, Tcmn hubiera obtenido una excepción...

¿ Será debido a la versión de Delphi o Firebird ? :confused:


Un saludo.

Casimiro Notevi 07-02-2011 22:00:05

Cita:

Empezado por ecfisa (Mensaje 390231)
¿ Será debido a la versión de Delphi o Firebird ? :confused:
Un saludo.

Creo que seguramente no es ese el proceso que realiza Tcmn. Pienso que después de grabar no edita, sino que hace otra cosa, sale del programa, etc. y luego en esa tabla abierta es cuando edita. Pero en ese caso estaría editando siempre sobre el registro primero de la misma.

ecfisa 07-02-2011 22:31:48

Si Casimiro, es mucho más probable.

Pero como el código en el mensaje parecía una prueba concreta, se me pasó esa posibilidad.

La mala costumbre de presuponer... :(


Un saludo.:)

Tcmn 07-02-2011 22:40:51

Cita:

Empezado por Casimiro Notevi (Mensaje 390236)
Creo que seguramente no es ese el proceso que realiza Tcmn. Pienso que después de grabar no edita, sino que hace otra cosa, sale del programa, etc. y luego en esa tabla abierta es cuando edita. Pero en ese caso estaría editando siempre sobre el registro primero de la misma.

Los pasos para dar de alta los registros son los siguientes:
1.- Presionar boton "INICIAR MODIFICACIONES".
2.- Dar de alta los registros que se quieran y editar los mismos que se acaban de dar de alta asi como los que previamente existian en la tabla con un DBGrid y ademas un DbNavigator.
3.- Presionar boton "CONFIRMAR TODO". El cual ejecuta:
Código Delphi [-]
 
Transaccion.Commit;
o bien el boton "DESHACER TODO". Con la sentencia:
Código Delphi [-]
 
Transaccion.Rollback;

En escencia es lo que se hace. Espero ayude en esta controversia y confusion.

Casimiro Notevi 07-02-2011 23:04:53

Cita:

Empezado por ecfisa (Mensaje 390240)
La mala costumbre de presuponer... :(
Un saludo.:)

Bueno, también puedo estar equivocado :)

Casimiro Notevi 07-02-2011 23:06:32

Cita:

Empezado por Tcmn (Mensaje 390242)
1.- Presionar boton "INICIAR MODIFICACIONES".
2.- Dar de alta los registros que se quieran y editar los mismos que se acaban de dar de alta asi como los que previamente existian en la tabla con un DBGrid y ademas un DbNavigator.
3.- Presionar boton "CONFIRMAR TODO". El cual ejecuta:

Ahí está el meollo de la cuestión, en el punto 2, ¿cómo está hecho exactamente?

Tcmn 07-02-2011 23:22:15

Pues lo que puedo mencionar es que mas alla de poner el DBGrid y DBNavigator en el formulario, conectar la propiedad DataSource y poner nombre a las columnas para que fuera mas entendible no hice nada mas. Tal vez se me ha pasado algo porque ahorita volvi a hacer pruebas, pero si usare el commitretaining en cada AfterPost de las tablas.

ecfisa 07-02-2011 23:31:33

Hola.

Ahora sí que estoy confundido...

Según el primer post usas:
Código Delphi [-]
  Tabla.Insert;
  tablaCAmpo1.Value:='ValorAl insertar Campo1';
  tablaCAmpo2.Value:='ValorAl insertar Campo2';
  tablaCAmpo3.Value:='ValorAl insertar Campo3';
  Tabla.Post;
y
Código Delphi [-]
  Tabla.Edit;
  tablaCAmpo2.Value:='Valor nuevo al Editar Campo2';{Modifico lo que hay en un campo}
  Tabla.Post;
Pero esto no es necesario si usás un TDBNavigator para realizar los ingresos y/o modificaciones sobre el TDBGrid.

Otra cosa,
Cita:

1.- Presionar boton "INICIAR MODIFICACIONES".
2.-Dar de alta los registros que se quieran
Si usas un menu/boton/etc, que diga "INICIAR MODIFICACIONES" y allí le permites ingresar datos, vas a confundir al usario.

Tal vez viendo el código se pueda encontrar el problema.

Un saludo.

Casimiro Notevi 08-02-2011 00:21:02

¿Y qué dataset estás usando?

Tcmn 08-02-2011 00:22:08

Puros IBDataset

Casimiro Notevi 08-02-2011 00:48:52

¿Y qué sqls tienes puesto?

Tcmn 08-02-2011 00:52:56

selectSQL:
Código SQL [-]
select CLAVEU, CONSEC, FECHA, HORAMOVIM, MONTO, NUM_CONT,  NOMBREUSUARIO, CLAVE_ABONO_CONTROLDIARIO  from ABONOS where num_cont=:num_cont order by consec
RefreshSQL:
Código SQL [-]
select CLAVEU, CONSEC, FECHA, HORAMOVIM, MONTO, NUM_CONT, NOMBREUSUARIO, CLAVE_ABONO_CONTROLDIARIO from ABONOS where consec=:consec
ModifySQL:
Código SQL [-]
update abonos set CLAVEU=:ClaveU, CONSEC=:Consec,  MONTO=:Monto, NUM_CONT=:Num_Cont,  NOMBREUSUARIO=:NOMBREUSUARIO,  CLAVE_ABONO_CONTROLDIARIO=:CLAVE_ABONO_CONTROLDIARIO where consec=:old_consec
InsertSQL:
Código SQL [-]
insert into abonos  (CLAVEU, CONSEC, MONTO, NUM_CONT,  NOMBREUSUARIO, CLAVE_ABONO_CONTROLDIARIO) values (:CLAVEU, :CONSEC, :MONTO, :NUM_CONT, :NOMBREUSUARIO, :CLAVE_ABONO_CONTROLDIARIO)
DeleteSQL:
Código SQL [-]
delete from abonos where consec=:old_consec

guillotmarc 08-02-2011 12:06:17

Pues a mi me parece que vuestro sistema no funciona como esperáis en algún punto.

Cualquier alta o modificación que aún no haya sido confirmada su transacción, no será visible desde otras transacciones.

Es por ello que si estás viendo "ValorAl insertar Campo2", eso tiene que ser debido a que la inserción ya ha sido confirmada. En caso contrario ese registro ni siquiera existiría.

NOTA: Por cierto, es una pésima idea el mantener transacciones abiertas pendientes de confirmar. Estás pidiendo a gritos tener deadlocks por conflictos de actualización (amén de otros efectos peregrinos que conllevan las transacciones abiertas, como el engorde de la base de datos, y su caída de rendimiento). Esta es la mayor fuente de problemas en Firebird, que he visto que tienen habitualmente los programadores.

Personalmente si quieres tener datos en pantalla, introducidos por el usuario, pero no trasladarlos a la base de datos hasta que no se confirme el total de la pantalla. En lugar de hacerlo medante una transacción abierta, yo lo hago entrando los datos en un ClientDataset (un Dataset en memoria local del equipo cliente), y pasándolos a la base de datos solo al momento en que se confirma la pantalla. De esta forma la transacción de actualización solo está activa unas milésimas de segundo.

Casimiro Notevi 08-02-2011 12:19:24

Opino, como casi siempre, igual que guillotmarc.
En lugar de ClientDataSet acostumbro a usar tablas en memoria.

Tcmn 08-02-2011 15:48:08

Que buenas observaciones, nunca pense que afectara de esa manera. Las tomare en cuenta pues como es mi primer sistema con Firebird y cliente/servidor valoro mucho cualquier sugerencia que tengan.

Gracias


La franja horaria es GMT +2. Ahora son las 17:52: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