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)
-   -   refresco de los datos (https://www.clubdelphi.com/foros/showthread.php?t=42984)

fedelphi 27-04-2007 15:40:09

refresco de los datos
 
Hola a todos, tengo una duda sobre el refresco de los datos en una PC que se conecta remotamente al servidor firebird. Las terminales son todas con W98 y firebird esta sobre W XP, y utilizo Delphi 7, IBx para conectarme. El problema es que cuando ingreso datos en una terminal va todo bien en esta, pero en el servidor no veo esos cambios hasta que no finalizo la aplicacion en la terminal. Que debo realizar para que estos cambios se reflejen inmediatamente en el servidor?
Muchas gracias
Fede

TJose 27-04-2007 15:46:15

hola fedelphi

Estoy casi seguro que el problema está en el manejo de las transacciones. No estas ejecutado el commit luego del (de los) insert/update/delete.
Por ese lado está la solución.

Saludos
TJose

fedelphi 03-05-2007 18:36:36

De vuelta, he tratado de manejar las transacciones pero al hacer un
IBTransaction1.StartTransaction me sale el error "Transaction is active" y si no activo el IBTransaction1 al hacer el primer commit todo bien, pero luego me sale el error "Cannot perform this operation on a closed dataset". Es que cierra la tabla al hacer un commit? Creo que tengo un lio con esto de las transacciones.
Gracias
Fede

egostar 03-05-2007 18:51:14

Yo tuve ese mismo problema y lo resolví (con ayuda del foro, claro) agregando otra transacción para insertar un registro.

Aún no encuentro el porque pero en mi programa el IBTransaction1 permanece activa y despues de realizar las consultas y procesos para grabar un registro no puedo usar el IBTransaction1, así que lo que hice (no se si es correcto, pero me funcionó) es agregra otro IBTransaction2 y con el realizar mi proceso de insert.

Aquí puedes ver el hilo que hago mención, espero te ayude.

Salud OS.



fedelphi 05-05-2007 02:11:02

Egostar creo que despues de investigar un poco con la informacion del hilo que diste en el mensaje anterior llegue a una solucion con los aportes de ronpablo, muchas gracias ronpablo. Esto es para que me corrijan por favor si estoy equivocado, ya que estoy aprendiendo, ya que son observaciones de practicar e investigar y la experiencia luego nos dara la razon si es que la tenemos. Bueno primero lo que pasaba es que al realizar el commit IBTransaction1.Commit, se desctiva la transaccion y todas las tablas por lo que sale el error "no se puede realizar la operacion en un dataset cerrado" entonces lo hice asi:
Código Delphi [-]
try
            if not modulodatos.IBTransaction1.Active then
              modulodatos.IBTransaction1.StartTransaction;
            if not Modulodatos.IBTAlmacen.Active then
              Modulodatos.IBTAlmacen.Active:=True;
            modulodatos.IBTAlmacen.Append;
            modulodatos.IBTAlmacen.FieldByName('ID_ALMACEN').AsInteger:=1;
            modulodatos.IBTAlmacen.FieldByName('NRO_TICKET').AsString:=ECodigo.Text;
            modulodatos.IBTAlmacen.FieldByName('ID_SUCURSAL').AsInteger:=Tag; //en el tag del este form paso el id de la sucursal desde el form ppal
            modulodatos.IBTAlmacen.FieldByName('ID_TICKET').AsInteger:=id_ticket;
            modulodatos.IBTAlmacen.FieldByName('FECHA_PRESENTACION').AsDateTime:=Date;
            modulodatos.IBTAlmacen.FieldByName('MONTO').AsFloat:=Monto;
            modulodatos.IBTAlmacen.FieldByName('FECHA_INGRESO').AsDateTime:=Date;
            modulodatos.IBTAlmacen.FieldByName('NRO_CAJA').AsInteger:=RGCajas.ItemIndex+1;
            modulodatos.IBTAlmacen.Post;
            modulodatos.IBTransaction1.CommitRetaining;

           
          except
            on E:Exception do
            begin
              modulodatos.IBTransaction1.Rollback;
              showmessage('Error al insertar en base de datos. '+e.Message);
            end;
          end;

entonces con el commit se cierra todo lo que dije anteriormente, pero con commitretaining no se cierran, siguen en el mismo estado en el que estaban cuando empieza la transaccion. Espero haber sido de ayuda, ah y me olvidaba, gracias a caral tambien por lo de la excepcion con el rollback, le agregue el mensaje para saber en caso de que se produzca algun error saber de que se trata. Saludos a todos y muchas gracias!!!!!
Fede

Lepe 05-05-2007 02:45:03

Los IBX no los he usado. Yo uso MDOLIB que son derivados de los IBX, tiene una propiedad DefaultAction que la tengo puesto a commit y la propiedad commitAfterpost a true. De esta forma me olvido de las transacciones (de momento).

Por otra parte, para que los cambios de una transacción se vean (en el caso de un commit), se debe hacer un commit, y después cerrar el dataset y volverlo a abrir ¿engorroso? sigue leyendo.

Para actualizar los datasets de forma automática, tienes los eventos y el EventAlert de IBX. En un trigger del servidor lanzas un mensaje después de insertar:
Código SQL [-]
  post_event 'Nuevo_Cliente';
En la ventana que quiera recibir ese mensaje, añades un componente IBEventAlert y registras el mensaje 'Nuevo_cliente'. El componente tiene un evento OnEvent y allí ordenas cerrar los datasets y volver a abrirlos.

El commitRetaining mantiene el contexto de la transacción que se inició; no se recomienda abusar de él.

PD: Para entender como funcionan, deberías leer los pdf acerca de las transacciones de Interbase, que son aplicables a Firebird.

Saludos

fedelphi 05-05-2007 15:06:42

Cita:

Empezado por Lepe

PD: Para entender como funcionan, deberías leer los pdf acerca de las transacciones de Interbase, que son aplicables a Firebird.

Lepe me podrias decir donde se encuentran estos pdf?

Lepe 05-05-2007 20:24:51

www.ibphoenix.com apartado de Documentacion. Eso si, vienen en inglés.

Saludos

Delphius 05-05-2007 20:26:42

Yo he descarga este artículo

Ha decir verdad, ya no me acuerdo como llegué a él... Si vi el enlace en un post o si fue buscando en google...

Tal vez te pueda interesar esta busqueda realizado en google.

Saludos,
PD: A también me está costando un poquito entender esto de las transacciones.


sitrico 19-05-2007 08:17:39

Me uno al tema
 
Estoy tratando de hacer que se ejecute el evento, pero no me funciona.

Uso D7, FB 2.0.1 y MDO.

En la base de datos defino el procedimiento:

Código SQL [-]
CREATE PROCEDURE ACTUALIZARCITAS 
as
begin
  post_event 'ACT_CITAS';
  suspend;
end^
GRANT EXECUTE ON PROCEDURE ACTUALIZARCITAS TO SYSDBA;

// ¿ que hace la ultima línea ?

Que lanzo despues con varios triggers:

Código SQL [-]
CREATE TRIGGER CI_CITAS_EVENT_NUEVA FOR CI_CITAS
ACTIVE AFTER INSERT OR UPDATE OR DELETE POSITION 0
AS
begin
EXECUTE PROCEDURE ACTUALIZARCITAS;
end

en delphi pongo un componente: MDOEvents con la base de datos asignada

Código Delphi [-]
procedure TfCitas.MDOEvents1EventAlert(Sender: TObject; EventName: String;
  EventCount: Integer; var CancelAlerts: Boolean);
begin
If EventName = 'ACT_CITAS' then
   MostrarCitas;  // = refresh
end;

Pero cuando incorporo una nueva cita (INSERT) desde otro módulo de la aplicación (otro exe) no ocurre el evento.

Lo único "raro" es que en mi datamodule defino 2 transacciones Una "Read commited" (read_committed, rec_version, nowait) para los SELECT y otra Read-Write table stability (write, consistency) para insert, update y delete.

¿me falta algo?

Edito:

inclui esto y tampoco funciona:

Código Delphi [-]
procedure TfCitas.FormActivate(Sender: TObject);
begin
If Not MDOEvents1.Registered Then
   MDOEvents1.Registered := true;
end;

Lepe 19-05-2007 08:55:07

No necesitas el procedimiento almacenado. Con el disparador sobra:
Código SQL [-]
CREATE TRIGGER CI_CITAS_EVENT_NUEVA FOR CI_CITAS
ACTIVE AFTER INSERT OR UPDATE OR DELETE POSITION 0
AS
begin
 post_event 'ACT_CITAS'
end

En el mdoRegisterEvent, necesitas añadir el evento que quieres esperar, dado que, en la base de datos puedes lanzar muchos eventos, pero una ventana de tu programa solo quiere enterarse de uno de ellos:
Código Delphi [-]
// solo hace falta registrarlo 1 vez, por ejemplo, al crear el form

const CitaModificada = 'ACT_CITAS';


procedure TfCitas.FormCreate(Sender: TObject);
begin
with mdoevents1 do
begin
  Add(CitaModificada);

If Not MDOEvents1.Registered Then
   MDOEvents1.Registered := true;
end;

Como sabrás, el evento lanzado por el SGBBDD lo recogerá todas las aplicaciones delphi que esten accediendo a esa Base de datos, pero solo le llegará el mensaje a la ventana que tenga registrado dicho mensaje.

Como has visto, he definido una constante CitaModificada, es muy fácil equivocarse al escribir el string, y con una sola letra que varíe, delphi no recibirá dicho evento, y empezarás a creer que Firebird no funciona bien o le echas la culpa a MDO. Usando constantes, te aseguras de no cometer errores mecanográficos. Por el bien de tu salud mental, te lo recomiendo encarecidamente :D :D.

El evento mdoEventAlert1.OnEvent lo tienes bien definido, por ello no comento nada más.

Saludos

sitrico 19-05-2007 17:42:02

Gracias Lepe, con ese cambio ya se disparan los eventos :D

Ahora me genera unos errores:
System error 5 acceso denegado (creo que asociados al nowait de la transacción).

Si lo quito me aparece lock conflic on mo wait transaction

Lepe 20-05-2007 10:46:34

Ya ese tema es totalmente distinto, y puede ser precisamente derivado de los mensajes.

Abres un dataset, que de alguna forma depende de las citas (foreign key, por ejemplo), después abres otro dataset que hace un update a la tabla citas, se dispara el mensaje, se recibe el EventAlert que cierra y abre el dataset de citas.... pero el primer dataset, que se abrió antes no se ha cerrado, puesto que dependía de las citas, tendrás esos conflictos.

Bueno, sé que lo he explicado fatal, pero vamos, la solución consiste en cerrar todos los datasets en el mismo orden en que se abrieron, incluso si se recibe un EventAlert.

Tampoco puedo asegurar al 100 % lo dicho, pero creo que hay "cierta lógica" en el comentario, ya que una transacción más antigua (la del primer dataset) no ha sido confirmada ni rechazada, mientras una más nueva (la tabla citas) si lo ha hecho.

Saludos

sitrico 20-05-2007 22:21:36

El problema está aqui:

Código Delphi [-]
   With l do
      Begin
      SQL.Clear;
      SQL.Add('SELECT  IDCITA, p.Cedula, P.IDPACIENTE, P.nombre, p.apellido, p.TLFCEL, p.SEXO, p.FCHNACIMIENTO,');
      SQL.Add('        FCHCITA, HORA, DURACION, IDAREA, IDESPECIALISTA,');
      SQL.Add('        STATUSCITA, OBSERVACIONES');
      SQL.Add('FROM    CI_CITAS C, dg_pacientes P');
      SQL.Add('Where p.idpaciente = c.idpaciente And FCHCITA = :FCHCITA AND IdAREA = :IDAREA');
      ParamByName('FCHCITA').AsDateTime := tp.Fecha;
      ParamByName('IDAREA').AsInteger := IdArea;
      Open; // aqui comienza el problema
      tp.MostrarCitasDelDia(l);  // While not eof do....
      Close;
      End;

Este es el ciclo crítico del Refresh (MostrarCitas) no se por que extraña razón al usar el debugger en la línea del Open; al presionar f8 o f7 en lugar de saltar a la siguiente línea (tp.MostrarCitasDelDia(c); ) salta otra vez al open; y de ahí en adelante sigue un comportamiento erratico.

Como se puede ver mis consultas están cerradas hasta tanto no se necesiten, (de hecho el código SQL lo coloque para el ejemplo pero se carga una sola vez en OnCreate);

Busqué eventos asociados a la DB, transaccion o query que pudieran cambiar la secuencia lógica pero NADA. ¿ Alguna idea ?

Nota: En otras ocaciones mi delphi ha tenido esos comportamiento erraticos pero generalmente se asociaban a eventos "inoportunos".

¿Hay alguna manera de forzar una sección de código para evitar que su ejecución sea interrumpida, algo como "DisableEvents"?

Por ahora no me quedo otra opción que "apagar" los eventos y usar una alarma (60seg) para refrescar automáticamente la información :(


La franja horaria es GMT +2. Ahora son las 13:00:41.

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