Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Otros temas > Trucos
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Los mejores trucos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 30-06-2006
Avatar de dec
dec dec is offline
Moderador
 
Registrado: dic 2004
Ubicación: Alcobendas, Madrid, España
Posts: 13.107
Poder: 34
dec Tiene un aura espectaculardec Tiene un aura espectacular
El tiempo de espera en ADO

¿Le ha tocado luchar alguna vez con el maldito mensaje "Tiempo de espera agotado" al intentar el acceso a una base de datos de SQL Server? En la época en que el BDE dominaba la faz de la Tierra, el problema se solucionaba retocando algunos parámetros en la configuración del alias o del controlador SQL Link. Los parámetros en cuestión eran (por si lo ha olvidado):

Parámetro - Significado

CONNECT TIMEOUT - Tiempo de espera para la conexión

MAX QUERY TIME - Tiempo de espera para abrir una consulta

TIMEOUT - Tiempo de espera para las restantes operaciones

El segundo parámetro podía configurarse tanto en el controlador como en un alias específico; los restantes, sólo en el controlador.

Pero al entrar ADO en escena, los viejos trucos ya no valen para mucho. ¿Cómo se puede indicar un tiempo de espera en ADO? La explicación que sigue no está sacada de ninguna documentación "oficial", sino que es fruto del respetable método conocido como "prueba y error". Además, los experimentos los he realizado exclusivamente con SQL Server 7. Espero que me disculpéis si encontráis alguna inexactitud.

El primer sitio donde se me ocurrió mirar fue en la configuración de una cadena de conexión. E inmediatamente encontré un par de parámetros, Connect Timeout y General Timeout. "¡Bien!" - me dije - "asunto concluido".

Me aguardaba una sorpresa, desgraciadamente. Por más que me empeñase en dar un valor explícito en estos parámetros, Delphi tozudamente insistía en ignorarlos. De hecho, como podrá comprobar, la propiedad ConnectionString se modifica cada vez que se activa la conexión, y cualquier asignación que hayamos realizado sobre estos valores desaparece por arte de magia.

Sospeché entonces que si Delphi jugaba con ConnectionString era porque prefería que indicásemos los tiempos de espera por medio de propiedades. Efectivamente, la clase TADOConnection define las propiedades ConnectTimeout y CommandTimeout. Probé a modificar estos valores en la conexión y ataqué con saña a una inmensa tabla que me estaba dando dolores de cabeza. ¡Arghh, aquello seguía sin funcionar!

Para abreviar, finalmente descubrí que la propiedad CommandTimeout de la conexión existe por la sencilla razón de que podemos ejecutar comandos SQL a través de este componente. El método necesario es:

Código Delphi [-]
function Execute(const CommandText: WideString;
   ExecuteOptions: TExecuteOptions = []): _RecordSet; overload;
procedure Execute(const CommandText: WideString;
   var RecordsAffected: Integer;
   ExecuteOptions: TExecuteOptions = [eoExecuteNoRecords]); overload;

Era necesario indicar de alguna forma el tiempo de espera de esta operación, y Borland decidió añadir esta propiedad al componente. Aclaro de paso que otras propiedades de TADOConnection tienen el mismo propósito, y que algunos de sus métodos que devuelven información de catálogo se implementan también como comandos.

Como podrá adivinar, el componente TADOCommand ofrece un CommandTimeout. Esto está muy bien para ejecutar operaciones de actualización y del lenguaje de definición de datos, pero tampoco nos resuelve el problema para una consulta. Por lo tanto, arrojé un TADOQuery en la superficie de un formulario ... ¡y vi que no existía una propiedad que controlase el tiempo de espera!

Sin embargo, la propiedad existe en TADODataSet, e indagando un poco más encontré que se introducía en la sección protected de la clase base TCustomADODataSet. La clase TADODataSet la hace pública, pero por algún oscuro designio Borland decidió que TADOQuery, TADOTable y TADOStoredProc eran merecedores de dicho privilegio.

Está claro que una solución posible es prescindir de las consultas y utilizar siempre TADODataSet. No es una idea descabellada porque, a diferencia de lo que sucede con los componentes del BDE, las implementaciones de las consultas, tablas y procedimientos almacenados de ADO están basadas en un mismo sistema de acceso, definido en la clase TCustomADODataSet, y se limitan a simplificar la especificación del conjunto de datos con el que deseamos trabajar.

¿Por qué entonces no utilizar TADODataSet y olvidarnos del asunto? Porque este componente exige que tecleemos la instrucción SQL en su propiedad CommandText, y alguno de los genios de Borland decidió dotar a esta propiedad del editor más incómodo, feo e inútil que he tenido la desdicha de encontrar. Si es usted una persona de nervios templados, pruebe su funcionamiento.

La solución final a la que recurrí consiste en un sucio truco para acceder a la propiedad escondida en un TADOQuery. He aquí el código que ejecuto durante la inicialización de un módulo de datos:

Código Delphi [-]
type
  TFriendDS = class(TCustomADODataSet);

procedure TDataModule1.Loaded;
var
  I: Integer;
begin
  inherited Loaded;
  for I := 0 to ComponentCount - 1 do
    if Components[i] is TADOQuery then
      TFriendDS(Components[i]).CommandTimeout := 120; Dos minutos
end;

La clave está en que el acceso la propiedad CommandTimeout se implementa del mismo modo en la clase base y en la clase derivada. Por lo tanto, si definimos una nueva clase derivada a partir de la original, se seguirá cumpliendo esta afirmación, y la bestial conversión de tipo que hacemos es, sin embargo, correcta y segura. Además, Object Pascal establece que dentro de la unidad donde se define una clase, cualquier objeto o procedimiento tiene acceso irrestricto a sus datos privados o protegidos; una implementación rudimentaria de la cláusula friend de C++. Al definir TFriendDataSet en el módulo de datos, obtenemos el derecho a manipular los recursos protegidos de la nueva clase, y esto incluye a los recursos heredados desde TCustomADODataSet. El círculo se ha cerrado.
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


La franja horaria es GMT +2. Ahora son las 19:20:51.


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