![]() |
Datenbank: MS Access • Version: 5? • Zugriff über: ADO
Abgebrochene ADOConnection wiederherstellen
Hallo alle miteinander,
ich habe ein Problem mit einer ADOConnection und brauche eure Hilfe. Ich habe eine Datenbankverbindung, die ab und an abbricht, weil mein Netzwerk zusammenbricht. Nun habe ich schon verschiedene Möglichkeiten probiert, um die Verbindung nach dem Zusammenbruch wiederherzustellen. Aktuell ist dies mein Quellcode zum Wiederaufbau der Verbindung:
Delphi-Quellcode:
Habt ihr ne Idee, warum der Wiederaufbau der Verbindung nie klappt?
//Globale Variable
var ADOC_CNC: TADOConnection; //Funktion zum Test der Verbindung function Test_CNCDB: boolean; var slHilf: TStringList; begin slHilf:=TStringList.Create; Result:=ADOC_CNC.Connected; try try if Result then ADOC_CNC.GetTableNames(slHilf); except Result:=false; end; finally slHilf.Free; end; end; //Funktion zum Herstellen der Verbindung function Open_CNCDB: boolean; begin Result:=true; try if Test_CNCDB then begin if Close_CNCDB then begin ADOC_CNC.ConnectionString:='...'; ADOC_CNC.LoginPromt:=false; end else begin //Fehler beim Trennen der Verbindung end end else begin ADOC_CNC.ConnectionString:='...'; ADOC_CNC.LoginPromt:=false; end; ADOC_CNC.Open; except Result:=false; end; end; //Funktion zum Trennen der Verbindung function Close_CNCDB:boolean; begin Result:=true; try ADOC_CNC.Close; except Result:=false; end; end; //Nun das Wiederherstellen der Verbindung im eigentlichen Programm if not Test_CNCDB then begin Close_CNCDB; if Open_CNCDB then //Wiederaufbau der Verbindung erfolgreich else //Verbindung konnte nicht wieder hergestellt werden end; Ich probiere seit Tagen an diesem Code rum und bekomme es einfach nicht hin. |
AW: Abgebrochene ADOConnection wiederherstellen
Frage: greifst du wirklich auf eine MS Access Datenbank über das Netzwerk (also eine MDB-Datei auf einem freigebenen Verzeichis) zu?
|
AW: Abgebrochene ADOConnection wiederherstellen
Zitat:
Ich mache es immer so:
Delphi-Quellcode:
Ich gehe davon aus, das die Verbindung ok ist ('happy path'). Wenn nicht, baue ich die Verbindung neu auf und versuche mein Glück nochmal.
Procedure DoDatabaseStuff;
Procedure _InnerDoDatabaseStuff; Begin // Lesen, beschreiben whatever der DB. End; Begin Try _InnerDoDatabaseStuff; Except Reconnect; _InnerDoDatabaseStuff; End End; Natürlich sollte man die Exception auswerten und nur bei Verbindungsproblemen neu verbinden, klar. Bei Neuaufbau der Verbindung kann man * Eine Meldung aufpoppen lassen * Es mehrmals versuchen * Durch eine eigene Exception den Programmfluss kontrolliert unterbrechen. |
AW: Abgebrochene ADOConnection wiederherstellen
Hallo ihr beiden,
also erst mal zu sx2008: Ja, ich greife auf eine mdb-Datei auf einem freigegebenen Verzeichnis zu (Data Source=\\123.123.123.132\ordner\datenbank.mdb). Aber wo liegt hier das Problem? @Furtbichler: Ich denke, wie man nun mitbekommt, dass ein reconnect notwendig ist, ist in meinem Fall erstmal zweitrangig. Mich interessiert eher, wie man den reconnect richtig macht, denn meiner funktioniert irgendwie nicht. Ich mache den reconnect folgendermaßen: 1. Testen, ob die Verbindung noch besteht (dazu nehme ich meine Funktion Test_CNCDB) => 2. wenn nicht, dann Verbindung trennen (dazu nehme ich meine Funktion Close_CNCDB) und anschließend Verbindung neu aufbauen (dazu nehme ich meine Funktion Open_CNCDB) |
AW: Abgebrochene ADOConnection wiederherstellen
1. Access über Netzlaufwerk: Schlecht, wegen Mehrbenutzerbetrieb usw. GANZ Schlect!
2. Wieso prüfen, ob die Verbindung besteht? Bau sie im Fehlerfall neu auf. Du könntest die Connection auch verwerfen und eine neue instantiieren.
Delphi-Quellcode:
Reicht doch, oder? Wenn das wider Erwarten nicht funktioniert, dann eben so:
MyADOConnection.Connected := False;
MyADOConnection.Connected := True;
Delphi-Quellcode:
Ich finde das simpel, viel simpler als deinen Ansatz.
MyADOConnection.Free;
MyADOConnection := TADOConnection.Create(Nil); MyADOConnection.ConnectionString := MyConnectionString; MyADOConnection.Connected := True; |
AW: Abgebrochene ADOConnection wiederherstellen
Da bin ich wieder.
Ich wollte soeben probieren, ob es so einfach geht. Habe dazu ein Testprogramm geschrieben. Über einen Button kann ich die Verbindung herstellen und über einen zweiten Button kann ich die Verbindung trennen. Mit dem dritten Button kann ich die Verbindung testen. So weit so gut. Nun stelle ich die Verbindung her. -> Klappt. Anschließend teste ich den Verbindungszustand. -> Klappt. Dann ziehe ich das Netzwerkkabel von meinem Rechner. -> Nun dürfte die Verbindung nicht mehr bestehen. Ich teste also wieder den Verbindungszustand. -> Ergebnis: Verbindung besteht. Das kann aber nicht sein!!! Den Test der Verbindung habe ich über 3 verschiedene Wege probiert: 1. Über die Eigenschaft Connected der ADOConnection
Delphi-Quellcode:
2. Über eine Abfrage des Tabellenkopfes
if ADOC_CNC.Connected
then //Verbindung besteht
Delphi-Quellcode:
3. Über eine Abfrage des Tabelleninhalts
try
ADOQ_CNC.GetTableNames(Hilfsstringliste); except //Verbindung unterbrochen end; Alle 3 Möglichkeiten funktionieren wie bei einer bestehenden Datenbankverbindung. Warum? Beziehungsweise was viel wichtiger ist, wie kann ich die Verbindung besser testen? |
AW: Abgebrochene ADOConnection wiederherstellen
Die Jetengine cached.
Du könntest eine Thread starten der eine eiegen Connection erzeugt, aufbaut und im OnTerminate den "Status" abliefert. nur als Beispiel ...
Delphi-Quellcode:
unit Unit5;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, DB, ADODB,ActiveX; type TCheckThread=Class(TThread) private FConn:TAdoconnection; FErr:Boolean; protected Procedure Execute;override; Destructor Destroy; override; public Property Error:Boolean read FErr; Constructor Create(Acon:TAdoConnection); End; TForm5 = class(TForm) ADOConnection1: TADOConnection; Memo1: TMemo; Button1: TButton; procedure Button1Click(Sender: TObject); private procedure MyOnTermiante(Sender: TObject); { Private-Deklarationen } public { Public-Deklarationen } end; var Form5: TForm5; implementation uses JRO_TLB,ADODB_TLB; {$R *.dfm} procedure TForm5.MyOnTermiante(Sender: TObject); begin if TCheckThread(Sender).Error then Showmessage('Fehler') else Showmessage('OK') end; procedure TForm5.Button1Click(Sender: TObject); begin With TCheckThread.create(AdoConnection1) do OnTerminate := MyOnTermiante; end; { TCheckThread } constructor TCheckThread.Create(Acon: TAdoConnection); begin inherited Create(false); CoInitialize(nil); FConn := Acon; FreeOnTerminate := true; end; destructor TCheckThread.Destroy; begin CoUninitialize; inherited; end; procedure TCheckThread.Execute; begin inherited; With TAdoConnection.Create(nil) do try ConnectionString:= Fconn.ConnectionString; try ConnectionTimeOut := 2; CommandTimeOut := 2; connected := true; except FErr := true; end; finally Free; end; end; end. |
AW: Abgebrochene ADOConnection wiederherstellen
So eine Verbindung bekommt vom gezogenen Kabel nichts mit.
Stell Dir vor, Du machst das im Firmennetz und die Datei liegt auf einem Server in Honolulu und der dortige Admin stolpert über das Netzwerkkabel (klar, und wird gefeuert, der Depp). Auf deinem PC ist die Welt so lange in Ordnung, bis Du versuchst, mit der Verbindung aktiv zu arbeiten. Bis dahin sagt die dir 'Alles in Butter, als mich hat noch niemand getrennt'. Du kannst natürlich vor jeder Aktion prüfen, ob eine Verbindung besteht. Aber dazu musst Du irgend etwas mit der Verbindung anstellen. Einige Treiber machen das, indem Sie ein 'SELECT 1' schicken. Dieser Befehl wird im Server (den Du nun mal nicht hast, aber egal) verarbeitet und dann wird eine Tabelle bestehend aus einer Zeile und einer Spalte als Ergebnis geschickt. Wenn das klappt, ist die Verbindung ok. Das 'SELECT 1' ist deshalb beliebt, weil es kaum Last erzeugt. Bei ACCESS müsste man das probieren, welcher Befehl schnell geht und trotzdem die Verbindung aktiv auffordert, sich mit der MDB-Datei zu beschäftigen. Allerdings würde ich es einfach drauf ankommen lassen und bei einem Fehler die Verbindung neu aufbauen. Alternativ kannst Du dir Gedanken über das 'Briefcase' Modell machen, bei der bewusst mit der Tatsache gearbeitet wird, das der Client nicht ständig Zugriff auf die Zentrale hat (Briefcase = Aktenkoffer => Außendienstmitarbeiter). |
AW: Abgebrochene ADOConnection wiederherstellen
Hallo Leute,
ich habe jetzt eine Lösung für mein Problem gefunden. Leider weiß ich zwar nicht wie man in meinem Fall einen Verbindungsausfall richtig erkennt, aber das Problem habe ich ein wenig umgangen. Das "SELECT 1" oder auch eine etwas tiefergehende Abfrage (bspw. nach dem ersten oder letzten Element einer bestimmten Tabelle) wie es mir von Iwo Asnet vorgeschlagen wurde, hat leider nicht funktioniert. Hier mein Lösungsweg: 1. Ich gehe davon aus, dass die Verbindung zu meiner Datenbank immer besteht. 2. Über eine AppException fange ich alle Fehler meines Programms ab. 3. Entsteht der Fehler bei einer Datenbankabfrage versuche ich automatisch die Verbindung neu aufzubauen. Dazu trenne ich die Verbindung und starte anschließend einen TTimer. 4. Bei jedem Start des Timerevents versuche ich nun die Verbindung wieder aufzubauen. Hier ein Teil des Quellcodes:
Delphi-Quellcode:
Damit ist zwar nicht alles geklärt, aber ich kann damit zumindest erst mal weiter.
//im AppException-Event des Programms...
ADOC_CNC.Connected:=false; Timer1.Enabled:=true; //nun das Timer-Event... procedure TForm1.Timer1Timer(Sender: TObject); begin //Verbindung neu aufbauen try ADOC_CNC.Connected:=true; if ADOC_CNC.Connected then Timer1.Enabled:=false; except //Verbindungsaufbau gescheitert -> neuer Versuch im nächsten Event end; end; Danke euch allen! |
AW: Abgebrochene ADOConnection wiederherstellen
Delphi-Quellcode:
Das sollte funktionieren.
Function ConnectionIsValid (aConnection : TADOConnection);
Begin Try aConnection.Execute('SELECT 1'); Result := True Except Result := False End End; |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:27 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz