2010-02-18 17 views
11

Je dois détecter lorsqu'un composant TAdoConnection a perdu la connexion avec le serveur. J'ai essayé d'utiliser l'événement OnDisconnect mais cela se déclenche uniquement lorsque la méthode Close est appelée ou que la propriété Connected est définie sur false.Comment puis-je détecter qu'un TadoConnection a perdu la communication avec le serveur?

Une autre option que j'ai essayé utilise un TTimer et l'exécution d'une requête comme celui-ci

SELECT 1 RESULT FROM DUAL 

en cas OnTimer, attrapant une exception qui se produit.

Y a-t-il une meilleure option pour détecter que la connexion a été perdue?

+2

SQL Server autorise Qry.ExecSQL avec SQL.Text = '' comme requête (mais pas ''). Cela peut être exécuté des centaines de fois par seconde. –

Répondre

11

Je vois la table DUAL. Signifie que vous utilisez l'Oracle :)

Pour la plupart (tous?) Des SGBD client/serveur, il n'y a aucun moyen de détecter qu'une connexion est perdue, sauf pour demander une action à un SGBD. Et il y a beaucoup de raisons, pourquoi une connexion est perdue. Peut être une panne de réseau, peut être ..., peut être un DBA arrêté une DB.

De nombreuses API SGBD, y compris Oracle OCI, ont des fonctions spéciales, permettant de faire un ping sur un SGBD. Le "ping" est une requête la plus petite possible à un SGBD. Le SELECT ci-dessus nécessite beaucoup plus de travail, qu'un tel ping. Toutefois, tous les composants d'accès aux données, notamment ADO, ne permettent pas d'exécuter une commande PING sur un SGBD à l'aide de l'appel ping de l'API DBMS. Ensuite, vous devez utiliser une commande SQL. Donc, le SELECT ci-dessus est correct avec ADO. Autre option - BEGIN NULL; FIN;. Il peut utiliser moins de ressources SGBD (pas besoin d'optimiseur, pas besoin de décrire un ensemble de résultats, etc.).

TTimer est OK. La requête doit être effectuée dans un thread, où la connexion correspondante est utilisée. Ce n'est pas un must, mais c'est un problème différent.

Le problème potentiel peut être de fermer une connexion, lorsqu'une connexion est perdue. Comme une fermeture de connexion peut générer une exception en raison de l'API SGBD peut être dans un état d'échec.

Type de cette ...

+1

Salut da-soft. si nous utilisons TADOConnection dans le thread principal, devrions-nous "pinguer" le sql du thread principal? aussi devrions-nous utiliser le même TADOConnection ou utiliser un autre "ping" TADOConnection? – zig

3

réponse @Dimitry est très bon. S'il est essentiel pour votre application de savoir si le connectino est perdu, l'approche TTimer (avec une opperation minimale).

Si vous voulez juste savoir quand une instruction échoue en raison d'une "communication perdue", vous pouvez utiliser l'événement Application.OnException et inspecter les propriétés Exception.

J'ai fait le code suivant comme exemple, en utilisant le composant ApplicationEvents. Est juste un projet avec l'idée, ne convient pas à la production.

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; 

Cordialement.

-1

Ceci est l'une des raisons pour lesquelles vous devez supprimer ADO et utiliser DBX. L'architecture Ado est basée sur le curseur du serveur et cela nécessite de ne pas perdre la connexion au serveur à tout moment. Si la connexion est perdue dans certaines circonstances, la connexion sera incapable de se relever. D'autre part, DBX est capable de se reconnecter presque jamais à cause de son architecture déconnectée.

+0

Ce n'est pas vrai. ADO peut être utilisé comme serveur en tant que curseurs client et permet d'appliquer un modèle de jeu de données déconnecté. De about.com: Pour créer un jeu d'enregistrements ADO déconnecté, vous devez d'abord définir la propriété ADODataSets CursorLocation sur "clUseClient". Ensuite, ouvrez le jeu d'enregistrements. Ensuite, définissez la connexion ADODatasets sur Nil. Ne fermez pas l'ADODataset. –

+0

Oui ADO peut fonctionner en mode porte-documents. Mais la réponse de DBX à ce problème est plus naturelle et prévisible. –

0

J'ai le même problème sur le pool de connexions. J'ai développé une classe TADOSQLConnectionPool pour aider à réutiliser la connexion pour les travaux de base de données DB.Quand je veux assigner une connexion à un thread, j'ai essayé de vérifier son état de santé en exécutant le travail minimum comme "Select 1". De cette façon, je serai sûr de connexion.Si elle échoue, je vais disposer de toutes les connexions à recréer à la prochaine demande.