2016-12-22 3 views
4

Je viens de décider de résoudre le problème de "Connection" quand un serveur de base de données MSSQL est redémarré, et la connexion est abandonnée éternellement.Delphi AdoConnection Reconnect

La seule solution à ce jour a été de redémarrer le programme, pas toujours si facile sur un serveur très lointain (et le problème doit d'abord être détecté).

** Le code ci-dessous semble fonctionner correctement, mais une personne ADO qualifiée peut-elle regarder plus en profondeur dans le code et voir les erreurs/problèmes ou améliorations nécessaires avec ce code? **

Type 
    TComponentHelper = class helper for TComponent 
  Procedure Reconnect(var AdoConn:TAdoConnection; ConnStr:String); 
  end; 

procedure TComponentHelper.Reconnect(var AdoConn: TAdoConnection; ConnStr: String); 
begin 
  if Assigned(AdoConn) then begin 
    FreeAndNil(AdoConn); 
      AdoConn := TAdoConnection.Create(Self); 
  AdoConn.ConnectionString := ConnStr; 
    AdoConn.LoginPrompt := false; 
      SetConnAdoComponent(Self,AdoConn); 
  AdoConn.Open; 
  end; 
end; 

procedure SetConnAdoComponent(aSrc:TComponent; var AdoConn:TAdoConnection); 
var 
    Ctrl : TComponent; 
    i : Integer; 
begin 
    if (aSrc = Nil) then Exit; 
    if (aSrc.ComponentCount <= 0) then Exit; 
    for i:=0 to aSrc.ComponentCount-1 do begin 
    Ctrl := aSrc.Components[i]; 
    if (Ctrl is TAdoQuery) then TAdoQuery(Ctrl).Connection := AdoConn; 
    if (Ctrl is TAdoTable) then TAdoTable(Ctrl).Connection := AdoConn; 
    if (Ctrl is TAdoDataset) then TAdoDataset(Ctrl).Connection := AdoConn; 
    end; 
end 

I Call Reconnect() de la partie d'exception dans un TForm ou TDataModule, AdoConn est le nom du composant TADOConnection et ConnStr est le connectionstring complet utilisé.

Except 
    On E:EOleException do begin 
    ReConnect(AdoConn,ConnStr); 
    end; 
    On E:Exception do begin 
    ReConnect(AdoConn,ConnStr); 
    end; 
End; 
+4

Je pense que la gestion de toutes les exceptions par reconnexion est un peu trop large. Vous pourriez vous retrouver avec un comportement très étrange lorsque vous essayez de vous reconnecter à la base de données, par exemple dans une erreur de requête ou des erreurs de mémoire. La deuxième chose est que vous détruisez l'objet adoconnection alors que d'autres composants l'utilisent encore, il pourrait même être utilisé dans l'une des écoles de la procédure où vous gérez votre exception. Je pense que vous êtes sur le mauvais chemin ici. Essayez et créez votre propre TAdoConnection qui gère cette erreur et peut se reconnecter. –

+0

Si le code fonctionne, cela appartient sûrement au site CodeReview stackexchange? Aussi, avez-vous simplement essayé 'Close' et' Open' la connexion? –

+1

@kobik: Comme d'habitude vous aviez raison sur ma réponse, que j'ai effacée. Merci. Je pourrais en avoir un autre plus tard. – MartynA

Répondre

2

Au lieu de détruire l'TADOConnection votre meilleure option est de remplacer le TADOConnection.ConnectionObject interne par un nouveau. par exemple.

uses ActiveX, ComObj, ADOInt; 

function CreateADOConnectionObject: _Connection; 
begin 
    OleCheck(CoCreateInstance(CLASS_Connection, nil, CLSCTX_INPROC_SERVER or 
    CLSCTX_LOCAL_SERVER, IUnknown, Result)); 
end; 

var 
    NewConnectionObject: _Connection; 
    ConnectionString: WideString; 
begin 
    ConnectionString := ADOConnection1.ConnectionString; 
    NewConnectionObject := CreateADOConnectionObject; 
    NewConnectionObject.ConnectionString := ConnectionString; 
    ADOConnection1.Close; 
    // set the new connection object 
    ADOConnection1.ConnectionObject := NewConnectionObject; 
    ADOConnection1.Open; 
end; 

Réglage ADOConnection1.ConnectionObject := NewConnectionObject va détruire le précédent interne FConnectionObject et définir un nouvel objet de connexion à utiliser par l'objet TADOConnection.

Aussi, vous devez gérer la spécifique EOleException.ErrorCode (probablement E_FAIL) au moment de l'exception afin que vous assurer que vous ne gérez pas d'autres exceptions qui n'a rien à voir avec votre problème.

Je n'ai pas essayé cela avec votre scénario spécifique (redémarrage SQL). Je vous laisse le soin de tester.

EDIT: Testé avec SQL Server 2014 et SQLOLEDB.1. Mon application connectée au SQL, et après avoir redémarré le SQL, je ne pouvais pas reproduire le comportement décrit "connexion est abandonnée éternellement". un Close/Open a fait le travail et le client s'est reconnecté.

+1

Sur votre edit, j'ai eu la même chose, même en tuant le processus sqlserver OP doit faire quelque chose de significativement différent pour 'Close' /' Open' pour ne pas fonctionner. –