2010-02-18 35 views
11

我需要檢測TAdoConnection組件何時與服務器失去連接。我試過使用OnDisconnect事件,但只有在調用Close方法或Connected屬性設置爲false時纔會觸發此事件。如何檢測到TadoConnection與服務器的通信中斷?

我使用TTimer和執行這樣的查詢

SELECT 1 RESULT FROM DUAL 
在OnTimer事件

,抓住出現的任何異常嘗試另一種選擇。

是否有更好的選擇來檢測連接是否丟失?

+2

SQL Server允許Qry.ExecSQL與SQL.Text =''作爲查詢(但不是'')。這可以每秒執行數百次。 – 2010-02-18 20:31:46

回答

11

我看到DUAL表格。意思是說,你正在使用Oracle:

對於大多數(所有?)客戶端/服務器DBMS來說,沒有辦法檢測到連接丟失,除了要求DBMS進行某些操作。有很多原因,爲什麼連接丟失。可能是網絡故障,可能是...,可能是DBA關閉了一個DB。

許多DBMS API(包括Oracle OCI)都具有特殊功能,允許ping DBMS。 「ping」是對DBMS最小的可能請求。上面的SELECT需要比ping更多的工作。

但並非所有數據訪問組件(包括ADO)都允許使用DBMS API Ping調用來ping DBMS。然後你必須使用一些SQL命令。所以,上面的SELECT對於ADO是正確的。其他選項 - BEGIN NULL;結束;。它可能使用較少的DBMS資源(不需要優化器,不需要描述結果集等)。

TTimer確定。查詢應該在使用相應連接的線程中執行。雖然不是必須的,但它是一個不同的問題。

潛在的問題可能是在連接丟失時關閉連接。由於DBMS API可能處於失敗狀態,因此連接關閉可能會引發異常。

那種......

+1

嗨大柔。如果我們在主線程中使用TADOConnection,我們應該從主線程「ping」sql嗎?我們是否也應該使用相同的TADOConnection或使用不同的「ping」TADOConnection? – zig 2015-06-24 12:41:57

3

@Dimitry答案很好。如果您的應用程序知道connectino是否丟失,TTimer方法(使用最少的操作)至關重要。

如果您只是想知道何時由於「失去通信」而導致語句失敗,則可以使用Application.OnException事件並檢查Exception屬性。

我以下面的代碼爲例,使用ApplicationEvents組件。只是一個草案的想法,不適合生產。

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; 

此致敬禮。

-1

這是放棄ADO並使用DBX的原因之一。 Ado體系結構是基於服務器遊標的,並且此請求程序不會隨時丟失與服務器的連接。如果在某些情況下連接丟失,連接將無法重新啓動。另一方面,DBX由於其不連貫的架構,能夠重新連接到永遠。

+0

這是不正確的。 ADO可以用作客戶端遊標的服務器,並允許應用斷開連接的數據集模型。從about.com: 爲了創建斷開連接的ADO記錄集,您必須首先將ADODataSets CursorLocation屬性設置爲「clUseClient」。然後打開Recordset。然後將ADODatasets連接設置爲無。不要關閉ADODataset。 – 2010-02-19 11:40:21

+0

是ADO可以在公文包模式下工作。但DBX對這個問題的反應更自然,更可預測。 – 2010-02-19 20:58:56

0

我對連接池有同樣的問題。我開發了一個TADOSQLConnectionPool類來幫助重用線程DB工作的連接。當我想分配一個連接到一個線程時,我試圖通過運行最小的工作來檢查它是否健康,如「選擇1」。通過這種方式,我將確定連接。如果失敗,我將在下次請求時處理所有連接以重新創建。