2010-02-18 17 views
11

Necesito detectar cuando un componente TAdoConnection ha perdido la conexión con el servidor. Intenté utilizar el evento OnDisconnect pero esto solo se dispara cuando se llama al método Close o la propiedad Connected se establece en false.¿Cómo puedo detectar que TadoConnection haya perdido la comunicación con el servidor?

Otra opción que he probado es el uso de un TTimer y ejecutar una consulta como esta

SELECT 1 RESULT FROM DUAL 

en caso AlCronómetro, la captura de cualquier excepción que se produce.

¿Hay una mejor opción para detectar que se perdió la conexión?

+2

SQL Server permite Qry.ExecSQL con SQL.Text = '' como una consulta (pero no ''). Esto se puede ejecutar cientos de veces por segundo. –

Respuesta

11

Veo la tabla DUAL. Significa que está utilizando Oracle :)

Para la mayoría (¿todos?) Del cliente/servidor DBMS no hay manera de detectar, que una conexión se pierde, excepto para pedirle a un DBMS que realice alguna acción. Y hay muchas razones por las cuales se pierde una conexión. Puede ser una falla de la red, puede ser ..., puede ser un DBA que cierra un DB.

Muchos DBMS API, incluido Oracle OCI, tienen las funciones especiales, lo que permite hacer ping a un DBMS. El "ping" es la solicitud más pequeña posible para un DBMS. El SELECT anterior requiere mucho más trabajo, que dicho ping.

Pero no todos los componentes de acceso a datos, incluido ADO, permiten hacer ping a un DBMS, utilizando la llamada de ping de la API de DBMS. Entonces debes usar algún comando SQL. Entonces, el SELECCIONADO anterior es correcto con ADO. Otra opción - BEGIN NULL; FIN;. Puede estar utilizando menos recursos de DBMS (sin necesidad de optimizador, no es necesario describir un conjunto de resultados, etc.).

TTimer está bien. La consulta debe realizarse en un subproceso, donde se utiliza la conexión correspondiente. No es obligatorio aunque, pero es un problema diferente.

El posible problema puede ser cerrar una conexión, cuando se pierde una conexión. Como el cierre de una conexión puede generar una excepción debido a que la API DBMS puede estar en un estado fallido.

Tipo de eso ...

+1

Hola da-soft. si usamos TADOConnection en el hilo principal, ¿deberíamos "hacer ping" al sql desde el hilo principal? también deberíamos usar la misma conexión TADO o usar una conexión TADO "ping" diferente? – zig

3

@Dimitry respuesta es muy buena. Si es crítico para su aplicación saber si se ha perdido el connectino, el enfoque TTimer (con una operación mínima).

Si solo quiere saber cuándo falla una declaración debido a una "comunicación perdida", puede usar el evento Application.OnException e inspeccionar las propiedades de Exception.

Hice el siguiente código como ejemplo, utilizando el componente ApplicationEvents. Es solo un borrador con la idea, no apto para producción.

uses 
    ComObj; 

procedure TForm2.ApplicationEvents1Exception(Sender: TObject; E: Exception); 
var 
    EO: EOleException; 
begin 
    if E is EOLEException then 
    begin 
    EO := EOleException(E); 
    //connection error (disconnected) 
    if EO.ErrorCode = E_FAIL then 
    begin 
     try 
     try 
      ADOConnection1.Close; 
     except 
      ; 
     end; 
     ADOConnection1.Open; 
     ShowMessage('Database connection failed and re-established, please retry!'); 
     except 
     on E:Exception do 
      ShowMessageFmt('Database connection failed permanently. ' 
      + 'Please, retry later'#13'Error message: %s', [E.Message]); 
     end; 
    end 
    else 
     ShowMessage(E.Message + ' ' + IntToStr(EO.ErrorCode)); 
    end 
    else 
    ShowMessage(E.ClassName + #13 + E.Message); 
end; 

Recuerdos.

-1

Esta es una de las razones para dejar ADO y usar DBX. La arquitectura Ado es basada en el cursor del servidor y esto no requiere perder la conexión con el servidor en cualquier momento. Si se pierde la conexión en algunas circunstancias, la conexión no podrá volver a levantarse. Por otro lado, DBX puede volver a conectarse casi siempre debido a su arquitectura desconectada.

+0

Esto no es verdad. ADO puede usar como servidor como cursores de cliente y permite aplicar un modelo de conjunto de datos desconectado. De about.com: Para crear un conjunto de registros ADO desconectado, primero debe establecer la propiedad ADODataSets CursorLocation en "clUseClient". Luego abre el Recordset. Luego configure la conexión ADODatasets en Nil. No cierre el ADODataset. –

+0

Sí ADO puede funcionar en modo maletín. Pero la respuesta de DBX sobre este tema es más natural y predecible. –

0

Tengo el mismo problema en el grupo de conexiones. Desarrollé una clase TADOSQLConnectionPool para ayudar a reutilizar la conexión para threads DB works.Cuando deseo asignar una conexión a un hilo, intenté verificar su estado ejecutando un trabajo mínimo como "Seleccionar 1". De esta forma, estaré seguro acerca de la conexión. Si falla, dispondré de todas las conexiones para volver a crear en la siguiente solicitud.

Cuestiones relacionadas