Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Conexión con bases de datos
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Conexión con bases de datos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 09-05-2007
Flecha Flecha is offline
Miembro
 
Registrado: nov 2006
Posts: 59
Poder: 18
Flecha Va por buen camino
Question Prioridad de ejecución de eventos

Tengo un caso algo complejo de explicar. Así que primero expondré la pregunta y luego intentaré exponer el caso concreto.

La pregunta:
Tengo un TDataSet cualquiera (TTable o TQuery), y dos TDataSource que están enlazados a dicho TDataSet. También tengo programados los eventos OnDataChange de sendos TDataSource.
¿Existe alguna manera que forzar a que siempre se ejecute un OnDataChange antes que el otro?

Mi problema en concreto:
Me he creado una clase cuya finalidad es calcular el valor de una serie de campos calculados de forma centralizada en toda la aplicación. El equivalente a esto habría sido poner un montón de campos calculados en muchísimos TTable y TQuery, y repetir en todos los eventos OnCalcFields el mismo ritual de cálculo de todos esos campos, ya que las fórmulas serían siempre las mismas.
En su lugar he optado por crearme una clase que contiene un TDataSource y un TQuery. El TDataSource lo enlazo con TDataSet's externos a la clase, y el TQuery lo enlazo al TDataSource. Así consigo una relación "maestro-detalle" en la que el "maestro" es el TDataSet externo. El TQuery interno es el encargado de realizar los cálculos de campos calculados, y más cosas.
Todo me va perfecto excepto en una cosa. En ocasiones, el TDataSet externo tiene otro TDataSource relacionado a él, aparte del contenido en mi clase. En esos casos necesito que siempre se ejecute el evento OnDataChange del TDataSource de mi clase antes del OnDataChange del TDataSource externo a mi clase, pero por lo general sucede siempre al revés.

¿Alguna idea?
Responder Con Cita
  #2  
Antiguo 09-05-2007
Flecha Flecha is offline
Miembro
 
Registrado: nov 2006
Posts: 59
Poder: 18
Flecha Va por buen camino
Thumbs up ¡¡ Ya está !!


Ya he encontrado una solución. No es la que más me gusta, pero era la única posible.

En fin. Resulta que la clase TDataSet contiene una variable llamada FDataSources (de tipo TList) que contiene la lista de todos los TDataSources que apuntan a dicho TDataSet. Cuando a la propiedad DataSet de un TDataSource se le asigna un TDataSet, dicho TDataSource es añadido a dicha lista FDataSources del TDataSet al que apunta. Y cuando se asigna nil, el TDataSource es borrado de dicha lista.

Cuando se producen eventos en el TDataSet, éste hace uso de su lista FDataSources para "despertar" los eventos de los TDataSource que estén apuntando al TDataSet. Por tanto, los eventos de TDataSource que se ejecutan antes son los de aquellos TDataSource que estén los primeros de la lista FDataSource.

Para solucionar mi problema me habría bastado con acceder a la lista FDataSource y hacer uso de su método Move() (ya que es de tipo TList) para cambiar el orden de los TDataSource contenidos en ella y poner el mío el primero de la lista. Pero por desgracia, tanto FDataSource como los procedimientos que lo manejan son private, así que no se puede acceder a ellos desde fuera.

Así que he optado por otra solución. Partiendo de la variable global Application he buscado todos los TDataSource creados dentro de la aplicación y que estén apuntando al TDataSet en concreto. A todos esos TDataSource les rompo su relación con el TDataSet para que desaparezcan de la lista FDataSource. Después les vuelvo a relacionar con su TDataSet y al ser incorporados de nuevo a la lista FDataSource son incorporados al final de la misma. Conclusión: he conseguido que mi TDataSource pase al primer lugar de dicha lista y que sus eventos sean los primeros de todos en ejecutarse.
Misión cumplida.

Aquí os paso el código fuente del procedimiento que me hace eso que os comento, por si a alguien le valiera de algo:
Código Delphi [-]
    procedure ReOrdenarDataSource(Componente:TComponent; MiDataSource:TDataSource);
    var x:integer;
    begin
      //==================
      // Este procedimiento asegura que los eventos de mi TDataSource local
      // se ejecuten antes que ningún otro TDataSource que apunte al mismo
      // TDataSet.
      //==================
      //------ Recorro los componentes contenidos
      for x:=0 to Componente.ComponentCount-1 do begin
        //------ Si a su vez puede contener TDataSource, entro en él
        if (Componente.Components[x] is TForm)
        or (Componente.Components[x] is TDataModule)
        or (Componente.Components[x] is TQuickRep)
        Then Begin
          ReOrdenarDataSource(Componente.Components[x], MiDataSource);
          Continue;
        End;
        //------ Busco otros TDataSource que apunten al mismo TDataSet
        {$B-}
        if (not (Componente.Components[x] is TDataSource))
        or (not (TDataSource(Componente.Components[x]).DataSet = MiDataSource.DataSet))
        or (Componente.Components[x] = MiDataSource))
        then Continue;
        //------ Rompo la relación entre el TDataSource y el TDataSet
        TDataSource(Componente.Components[x]).DataSet := nil;
        //------ Vuelvo a relacionar el TDataSource con el TDataSet
        TDataSource(Componente.Components[x]).DataSet := MiDataSource.DataSet;
      end;
    end;

La llamada a este procedimiento es esta:
Código Delphi [-]
  ReOrdenarDataSource(Application, MiDataSourceLocal);

Un saludo a todos.

Última edición por Flecha fecha: 10-05-2007 a las 11:30:03.
Responder Con Cita
  #3  
Antiguo 10-05-2007
drykea drykea is offline
Miembro
 
Registrado: abr 2007
Posts: 113
Poder: 17
drykea Va por buen camino
Hola Flecha.

Creo que la solución que buscas es muy simple, en el evento OnDatachange del datasource que quieres que se ejecute en segundo lugar, pones como primera instrucion del código una llamada al evento OnDatachange del datasource que quieres que se ejecute antes.


Quedaría algo así:

procedure TForm1.DataSource2DataChange(Sender: TObject; Field: TField);
begin
TForm1.DataSource1DataChange(TObject; TField);
end;

Espero que te sirva de ayuda.

Un saludo.
Responder Con Cita
  #4  
Antiguo 15-05-2007
Flecha Flecha is offline
Miembro
 
Registrado: nov 2006
Posts: 59
Poder: 18
Flecha Va por buen camino
Por supuesto que me vale drykea.
De hecho era la solución que me guardaba en la recámara por si no encontraba otra mejor.

Pero yo quería que mi objeto fuera completamente independiente del mundo exterior. Con la solución que propones estaría obligado a siempre acordarme (yo y cualquiera de mis compañeros) de incluir esa llamada dentro del evento que se ha de ejecutar en segundo lugar. Pero ¿qué hacer si en vez de haber sólo 2 TDataSource en juego (el mío y el otro externo) hay 3 o más (el mío, y 2 o más externos)? No puedo incluir esa llamada en todos los eventos del resto de eventos.

Con la solución que al final encontré me garantizo totalmente esa independiencia que buscaba y además que el evento de mi objeto se ejecutará siempre antes que el evento de todos los demás TDataSource.

Muchas gracias de todos modos.
Un saludo.
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
tratar eventos en ejecucion gallipi Varios 1 17-04-2007 14:13:34
Cambio de orden de ejecución de eventos JM75 OOP 2 31-01-2007 17:47:36
¿como abortar ejecución de eventos? pjjorda Varios 5 06-06-2006 21:59:59
Assignar eventos durante ejecución miguelml Varios 2 09-05-2006 11:12:53
Eventos en componentes creados en tiempo de ejecucion joumont OOP 3 27-12-2005 15:48:23


La franja horaria es GMT +2. Ahora son las 17:19:22.


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