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 13-02-2019
usuario1000 usuario1000 is offline
Miembro
 
Registrado: nov 2016
Posts: 86
Poder: 8
usuario1000 Va por buen camino
Unhappy Duda sobre grabación de registros

Buenas a todos,


Tengo el siguiente problema en una base de datos y que trabaja con datos reales y me tiene muy mosca, a ver si podéis echarme un cable.


Tengo una aplicacion hecha en Delphi 10 Seatle y que trabaja en red local con firebird, utilizo alrededor de 20 tablas. El problema viene que de vez en cuando y no siempre, algún usuario introduce unos datos y no se refleja de inmediato en la base de datos, se quedan en el limbo, y se llega a actualizar cuando cierro el servidor ó la aplicación cliente (se me olvidaba comentar que la aplicación es DATASNAP). He revisado uno de los procedimiento que me ha fallado y tiene puesto su correspondiente transacciones.StartTransaction, Transacciones.commit ó si procede transacciones.rollback.



Tengo una conexion creada y asociado a esa conexión tengo un componente TFDTransaction, del cual tiro para realizar las transacciones en cada escritura que se realiza a la base de datos.


¿que puede estar pasando?, ¿como hago para que no se queden datos colgados y se graben directamente sin esperar un segundo, existe alguna instruccion?



Me estoy deprimiendo....


Gracias a todos.
Responder Con Cita
  #2  
Antiguo 13-02-2019
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Crea una prueba aislada del problema, colocando en una nueva aplicación los elementos esenciales del proceso, como son los componentes de acceso y conexión de base de datos. Un simple formulario, con un botón para intentar reproducir el problema.

Es normal abrumarse ante un bug misterioso cuando este ocurre a mitad del bosque. Pero es un poco más fácil encontrar la causa si se recorta ese pequeño trozo de bosque y se planta en la maceta de tu ventana.

¡Y nos muestras el código!

Saludos.
Responder Con Cita
  #3  
Antiguo 13-02-2019
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.021
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Un commit que falta por ahí, también
Responder Con Cita
  #4  
Antiguo 13-02-2019
usuario1000 usuario1000 is offline
Miembro
 
Registrado: nov 2016
Posts: 86
Poder: 8
usuario1000 Va por buen camino
Gracias por las respuestas, me he limitado a ejecutar un proceso sencillo y he hecho paso a paso lo siguiente y algo falla, me explico:


Código Delphi [-]
  transacciones.StartTransaction;
   try
      QExpedientes.ExecSQL;// (aquí paro la ejecución y la ejecuto paso a paso)
      Result := 'Ok';
      transacciones.Commit;
    except
    on E: Exception do
      begin
         transacciones.Rollback;

      end;

   end;


1º Ejecuto el servidor en modo depuración. Es decir paso a paso. Tengo un stop puesto en la instrucción EXECSQL.
2º Ejecuto el Cliente en modo normal.
3º Ejecuto el SQLManager Lite para ver en todo momento los valores que toman los campos de un registro.
4º Modifico un registro en el cliente y pulso aceptar para que mande los datos al servidor con la correspondiente funcion.enviarDatos(dato1, dato2, dato3...);
5º En el servidor se ejecuta el proceso que he copiado mas arriba y se para la linea donde tengo el stop, y empiezo a ejecutar paso a paso.
6º Se ejecuta QExpedientes.ExecSQL y me voy a la base de datos y no observo modificación alguna, es de esperar que sea así, puesto que no ha llegado aún al commit.
7º Cuando se ejecuta la línea "transacciones.Commit", me voy de nuevo a la base de datos (SQLManager Lite) y le doy a refrescar para ver si ha cogido los nuevos datos y no los ha cogido, aún tiene los antiguos. Le doy a refrescar varias veces y nada de nada. Incluso ejecuto otro cliente y aparecen los datos antiguos. Deprimente.
8º Cierro la aplicación y ahora sí, estan los datos en la Base de Datos.


El problema que me encuentro es que en el momento que grabo un registro, no se actualiza la base de datos de inmediato, dando origen a un problema, que es que otro ususario se conecte y le lleguen unos datos que no sean los actualizados. De hecho me ha pasado ya y quiero evitar ese problema con la grabación inmediata de datos del cliente al servidor.


No sé que hago mal, en principio el proceso es muy sencillo, tal como he puesto más arriba. Supongo que será tocar alguna propiedad o algo del componente TFDTRansaction.


Espero me echen un cable.



Gracias anticipadas.
Responder Con Cita
  #5  
Antiguo 14-02-2019
Avatar de Caminante
Caminante Caminante is offline
Miembro
 
Registrado: oct 2010
Ubicación: Lima - Peru
Posts: 338
Poder: 14
Caminante Va camino a la fama
Hola


No conozco los componentes que usas pero podrias fijarte el nivel de aislamiento de las transaccion con un readcommited ya deberia leer los datos cambiados.


Espero sea util


Saludos
__________________
Caminante, son tus huellas el camino y nada más; Caminante, no hay camino, se hace camino al andar.
Antonio Machado
Responder Con Cita
  #6  
Antiguo 14-02-2019
usuario1000 usuario1000 is offline
Miembro
 
Registrado: nov 2016
Posts: 86
Poder: 8
usuario1000 Va por buen camino
Cita:
Empezado por Caminante Ver Mensaje
Hola


No conozco los componentes que usas pero podrias fijarte el nivel de aislamiento de las transaccion con un readcommited ya deberia leer los datos cambiados.


Espero sea util


Saludos



Gracias por tu respuesta.


El componente TFDFTransaction en su propiedad Isolation tiene asignado "xiReadCommited".



El TFDQuery que utilizo para realizar el "Update from ...." tiene en su propiedad Transaction asignado el componente TFDFTransaction.

En principio no veo nada raro.


Para que me funcione tengo que poner las siguienes instrucciones en el cliente:
Código Delphi [-]
resultado:= funcion.enviarDatosAServidor(dato1, dato2, dato3...);
if resultado = 'OK' then 

begin

      TFDConnection.connected := false;
      TFDConnection.connedted:= True;
end;


No me parece muy coherente cada vez que modifique un dato conectar y desconectar el cliente para que actualice la base de datos.


A ver si podemos arreglarlo de otra forma.


Gracias.
Responder Con Cita
  #7  
Antiguo 14-02-2019
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.021
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Ese componente fdtransaction ¿tiene una propiedad "base de datos", y está asignada?
Responder Con Cita
  #8  
Antiguo 14-02-2019
usuario1000 usuario1000 is offline
Miembro
 
Registrado: nov 2016
Posts: 86
Poder: 8
usuario1000 Va por buen camino
Cita:
Empezado por Casimiro Notevi Ver Mensaje
Ese componente fdtransaction ¿tiene una propiedad "base de datos", y está asignada?



Buenas tardes,


El componente en sí, no veo que tenga tal propiedad, no sé si está muy escondida por alguna subpropiedad, pero no la veo.




Como ultima medida estoy pensando en quitar todas las instrucciones de transacciones, a ver si delphi las ejecuta de forma automática y me arregla el problema, pero lo veo raro. Según tengo entendido cuando no ejecutas una transaccion delphi la ejecuta de forma automática, pero no lo hace.


Me gustaría ver como puedo arreglar este problema de que no me graba instantáneamente en las tablas de la base de datos.



Gracias por tu interés.
Responder Con Cita
  #9  
Antiguo 14-02-2019
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.021
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Cita:
Empezado por usuario1000 Ver Mensaje
El componente en sí, no veo que tenga tal propiedad, no sé si está muy escondida por alguna subpropiedad, pero no la veo.
¿Entonces tienes un componente base de datos y tiene asignado un componente transaction?
Responder Con Cita
  #10  
Antiguo 14-02-2019
usuario1000 usuario1000 is offline
Miembro
 
Registrado: nov 2016
Posts: 86
Poder: 8
usuario1000 Va por buen camino
Cita:
Empezado por Casimiro Notevi Ver Mensaje
¿Entonces tienes un componente base de datos y tiene asignado un componente transaction?

Por el lado del Servidor tengo los siguientes componentes:
- TFDConnetion, el cual tiene una propiedad "Transaction" donde tengo asignado el componente TFDTransaction
- TFDTransaction, elcula tiene una propiedad "Connection" donde tengo asignado al componente anterior (TFDConnection).
- Y distintos TFDQuery, en cada uno de ellos hay una propiedad "Transaction" que tiene asignado el TFDTransacction.



por el lado del Cliente, utilizo los siguientes componentes:
- TClientDataSet.
- TDataSetProvider.
- SQLConnection,


hay algunos más componentes, pero básicamentes son del mismo tipo.


Para las grabaciones de datos, utilizo funciones donde paso los parametros a grabar desde el cliente al servidor.



Saludos.
Responder Con Cita
  #11  
Antiguo 14-02-2019
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.021
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Entonces, no necesitas controlar tú mismo las transacciones.
Código Delphi [-]
QExpedientes.ExecSQL;
Y nada más.


Lo que no entiendo es eso de "en el lado del servidor" y "en el lado del cliente", ¿tienes un programa cliente, que conecta a un programa servidor, que conecta a la base de datos?
No sé si esos componentes funcionan así, pero me parece extraño.
Responder Con Cita
  #12  
Antiguo 14-02-2019
usuario1000 usuario1000 is offline
Miembro
 
Registrado: nov 2016
Posts: 86
Poder: 8
usuario1000 Va por buen camino
Cita:
Empezado por Casimiro Notevi Ver Mensaje
Entonces, no necesitas controlar tú mismo las transacciones.
Código Delphi [-]QExpedientes.ExecSQL;

Y nada más.


Lo que no entiendo es eso de "en el lado del servidor" y "en el lado del cliente", ¿tienes un programa cliente, que conecta a un programa servidor, que conecta a la base de datos?
No sé si esos componentes funcionan así, pero me parece extraño.



Perdón, no me he explicado bien. Lo que quiero decir es que tengo dos programas, uno es el servidor y otro el cliente. El cliente envia la información a grabar al servidor y el servidor está conectado a la base de datos mediante el componente TFDConnection, que por medio de TFDQuery (qExpedientes.ExecSQL) graba la información en la misma. Pero no lo hace al instante, tarda un tiempo, incluso demasiado. Es una aplicación DataSnap.



No sé si alguno de los componentes debo indicar algo para que la grabación sea inmediata, ya lo estuve revisando y no veo nada que me llame la atención.


Gracias por tu interés.
Responder Con Cita
  #13  
Antiguo 14-02-2019
Avatar de look
look look is offline
Miembro
 
Registrado: sep 2007
Ubicación: The Shire
Posts: 656
Poder: 17
look Va camino a la fama
Cita:
Empezado por usuario1000 Ver Mensaje
Buenas a todos,
..

..., algún usuario introduce unos datos y no se refleja de inmediato en la base de datos, se quedan en el limbo, y se llega a actualizar cuando cierro el servidor ó la aplicación cliente (se me olvidaba comentar que la aplicación es DATASNAP). ..


.
Hola amigo, firebird es una base de datos enteramente transanccional, es decir , todo los procesos empiezan siempre con un start transaction y finalizan con un commit, ...
cuando una transaccion esta en proceso y no termina con su respectivo commit, al cerrar la connecion , en tu caso cerrar el cliente o servidor, firebird toma el commit en ese momento, (autocommint), es por eso que solo ves los datos hasta que cierran la app cliente o server.
en resumen tienes que confirmar los datos con un commit, revisa esto, las querys que estas utilizando para hacer insert o update, deben tener asiganada la transanccion que tiene la base de datos, la base de datos tienen que tener asignada esa misma transaccion.
__________________
all your base are belong to us
Responder Con Cita
  #14  
Antiguo 14-02-2019
usuario1000 usuario1000 is offline
Miembro
 
Registrado: nov 2016
Posts: 86
Poder: 8
usuario1000 Va por buen camino
Cita:
Empezado por look Ver Mensaje
Hola amigo, firebird es una base de datos enteramente transanccional, es decir , todo los procesos empiezan siempre con un start transaction y finalizan con un commit, ...
cuando una transaccion esta en proceso y no termina con su respectivo commit, al cerrar la connecion , en tu caso cerrar el cliente o servidor, firebird toma el commit en ese momento, (autocommint), es por eso que solo ves los datos hasta que cierran la app cliente o server.
en resumen tienes que confirmar los datos con un commit, revisa esto, las querys que estas utilizando para hacer insert o update, deben tener asiganada la transanccion que tiene la base de datos, la base de datos tienen que tener asignada esa misma transaccion.

He revisado todas las transacciones y todas terminan con un Commit o con un RollBack. No hay ningún StartTransaction que se quede descolgado.


Además me he ido a un proceso de alta de registro en concreto que se ve facilmente en 3 líneas el proceso completo de StartTransaction y el commit seguidamente y no graba al instante en la base de datos.



No sé ya que propiedad tocar ni que hacer.


Quedo a la espera de vuestros comentarios.


Gracias.
Responder Con Cita
  #15  
Antiguo 14-02-2019
usuario1000 usuario1000 is offline
Miembro
 
Registrado: nov 2016
Posts: 86
Poder: 8
usuario1000 Va por buen camino
¿Existirá alguna instrucción para vaciar el buffer o algo parecido?


Recuerdo que en las tablas de delphi mas antiguos existía el "flushbuffer" para grabar inmediatamente, no sé por si acaso hay algo parecido.


Gracias.
Responder Con Cita
  #16  
Antiguo 15-02-2019
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.021
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Haz lo que te dijo Al González:
Cita:
Empezado por Al González Ver Mensaje
Crea una prueba aislada del problema, colocando en una nueva aplicación los elementos esenciales del proceso, como son los componentes de acceso y conexión de base de datos. Un simple formulario, con un botón para intentar reproducir el problema.
Es normal abrumarse ante un bug misterioso cuando este ocurre a mitad del bosque. Pero es un poco más fácil encontrar la causa si se recorta ese pequeño trozo de bosque y se planta en la maceta de tu ventana.
¡Y nos muestras el código!
Saludos.
Es que no podemos hacer mucho si no podemos "tocar y ver" tu programa.
Responder Con Cita
  #17  
Antiguo 15-02-2019
Avatar de Caminante
Caminante Caminante is offline
Miembro
 
Registrado: oct 2010
Ubicación: Lima - Peru
Posts: 338
Poder: 14
Caminante Va camino a la fama
Cita:
Empezado por usuario1000 Ver Mensaje
Gracias por tu respuesta.

Para que me funcione tengo que poner las siguienes instrucciones en el cliente:
Código Delphi [-]resultado:= funcion.enviarDatosAServidor(dato1, dato2, dato3...); if resultado = 'OK' then begin TFDConnection.connected := false; TFDConnection.connedted:= True; end;



No me parece muy coherente cada vez que modifique un dato conectar y desconectar el cliente para que actualice la base de datos.


Gracias.

Pues a mi no se tampoco me parece coherente cerrar la coneccion y volver a conectar. Si las transacciones estan configuradas correctamente deberia bastar con cerrar y abrir el dataset. Habria que ver como haces el proceso. Poruqe se supone que la transaccion (estando en readcommited) deberia poder leer las transacciones confirmadas. A mi siempre me ha funcionado; aunque nunca he usado datasnap.
__________________
Caminante, son tus huellas el camino y nada más; Caminante, no hay camino, se hace camino al andar.
Antonio Machado
Responder Con Cita
  #18  
Antiguo 15-02-2019
Avatar de Al González
[Al González] Al González is offline
In .pas since 1991
 
Registrado: may 2003
Posts: 5.604
Poder: 29
Al González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en brutoAl González Es un diamante en bruto
Es como si tuviera transacciones anidadas:
Código:
StartTransaction
  StartTransaction
  Commit
Commit
El "verdadero" commit es el último, pero es sólo una idea. Procura aislar el proceso en una aplicación mucho más sencilla.
Responder Con Cita
  #19  
Antiguo 15-02-2019
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 32.021
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Cita:
Empezado por Al González Ver Mensaje
Es como si tuviera transacciones anidadas:
Código:
StartTransaction
  StartTransaction
  Commit
Commit
El "verdadero" commit es el último, pero es sólo una idea. Procura aislar el proceso en una aplicación mucho más sencilla.
Casi seguro que es algo así. Está haciendo transacciones manualmente, cuando el componente ya las tiene asociadas implícitamente.
Responder Con Cita
  #20  
Antiguo 15-02-2019
usuario1000 usuario1000 is offline
Miembro
 
Registrado: nov 2016
Posts: 86
Poder: 8
usuario1000 Va por buen camino
Cita:
Empezado por Casimiro Notevi Ver Mensaje
Casi seguro que es algo así. Está haciendo transacciones manualmente, cuando el componente ya las tiene asociadas implícitamente.



Buenas


Como puedo averiguar si el componente las tiene asociada implicitamente. ¿Cual es la propiedad?.



Ayer por la noche quité todas las instrucciones de transacciones, para ver si se hacían de forma automática las grabaciones de manera implicita, quité el componente TFDTransaction y no funcionó. Así que lo dejé como estaba.


Lo he solucionado de forma provisional modificando el programa Cliente, cada vez que envío datos al programa Servidor, lo que hago es seguidamente desconectar y conectar al cliente del servidor, y así sí que se refleja inmediatamente la grabación. Pero como digo, no es una forma de hacerlo que me guste, aunque consigo lo que quiero. Seguiré investigando a ver que sucede.


No hago transacciones anidadas, un ejemplo es como el que sigue:
Código Delphi [-]
  transacciones.StartTransaction;
  try
    qCuentas.ExecSQL;
    Result:= 'Ok';
    transacciones.commit;
  Except
    on E: exception do
    begin
        transacciones.Rollback;
        raise;
    end;
  end;


Tan sencillo como eso y no graba cuando llega al commit.


Gracias por vuestros comentarios.
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
Grabacion macrossman Varios 2 06-04-2011 23:09:07
Duda registros valor 0 sql drykea SQL 6 13-03-2008 18:43:52
Duda sobre DFS enrique_84 Varios 2 08-06-2006 12:53:40
grabación jorodgar Windows 4 19-09-2005 12:22:42
Duda sobre busqueda de registros... hademon Varios 2 16-09-2005 20:26:17


La franja horaria es GMT +2. Ahora son las 13:05:17.


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