2012-12-12 151 views
9

在我的Datasnap客戶端應用程序中,我爲我的方法和ProviderConnection使用了1個TSQLConnection。 連接丟失時出現問題。 TSQLConnection.Connected和TSQLConnection.ConnectionState都無法捕捉到這一點。Mannaging SQLConnection/Datasnap通過客戶端 - 服務器斷開連接

當我的TSQLconnection打開但我失去了互聯網連接,或服務器停止。Datasnap客戶端應用程序出現很多錯誤。 (服務器方法或ClientDatasets)

我創建了一個函數來管理我的服務器方法的SQL連接。但是當例如關閉通過TDSProviderConnection連接的ClientDataset時會出現更多問題。

問:如何管理客戶端應用程序以安全捕獲TSQLconnection上的任何斷開連接。 問題:您如何管理停機時間,以及您如何處理未保存的客戶端狀態。

停機後重新連接不是問題。

當調用servermethod時:這會拋出異常。

tmpM:=TServerMethodsClient.Create(MYTSQLCONNECTION.dbxconnection,true); 

因此,我寫下一個方法來從我的datamodule用虛擬方法獲取TSQLCONNECTION。

function TDMForm.DSConnection: TSQLConnection; 
var 
    tmpM:TServerMethodsClient; 
begin 
    result:=nil; 
    if assigned(MYTSQLCONNECTION) then begin 
    tmpM:=TServerMethodsClient.Create(MYTSQLCONNECTION.dbxconnection,true); 
    try 
     try 
     tmpM.Ping; 
     result:=MYTSQLCONNECTION 
     except 
     ReconnectForm.ShowModal; // has a reconnect button that tries to reconnect + shutdownbutton 
     if ReconnectForm.modalresult=mrOK then 
      result:=MYTSQLCONNECTION 
     else 
      MainForm.Close; 
     end; 
    finally 
     tmpm.Free; 
    end; 
    end; 
end; 

我寫的方法這種方式,因爲只有找出如果連接丟失的方法是通過虛擬方法至極將拋出同樣的錯誤......然後我可以查詢重新連接或關閉程序。

編輯:(我期待某種一般的回答和指導方針,做了並且不不是我的代碼修正,這只是展示一下我在此刻做的。)

回答

3

我們在同樣的問題上掙扎 - 如何檢測連接何時中斷,以及如何正常重新連接。這就是我們最終做的事情,這對我們來說已經證明是非常成功的。

我們的用戶連接到DataSnap服務器以檢索數據並進行更改。通過TClientDataSet中的OnBeforePostOnBeforeDelete事件處理程序,將立即將所有記錄創建,更新和刪除操作送入數據庫。

由於您無法檢測到客戶端從DataSnap服務器強制斷開連接,直到您嘗試與服務器通信並發現連接已斷開,我們在應用程序的主窗體中添加了TApplicationEvents併爲OnException事件寫了一個事件處理程序。當我們看到一個EIdSocketError時,我們知道連接已經死亡,所以我們向用戶顯示一條消息,然後致電Abort,以便PostDelete不會發生在本地數據集中。用戶可以重新登錄,然後點擊保存刪除再次完成其以前的操作。

我們在全球的異常處理程序看起來是這樣的:

procedure TMainForm.AppEventsException(Sender: TObject; E: Exception); 
begin 
    if E is EIdSocketError then 
    begin 
    AppEvents.CancelDispatch; 
    MessageDlg('The connection to the database was lost. You must log in before you retry the failed action. Actual error message:'#13#10#13#10 + E.Message, mtError, [mbOK], 0); 
    Abort; 
    end; 

    if E is TDBXError then 
    begin 
    AppEvents.CancelDispatch; 
    MessageDlg('The database returned an error. If you cannot correct the issue, please contact customer service with the following database error message:'#13#10#13#10 + E.Message, mtError, [mbOK], 0); 
    Abort; 
    end; 

    // Show any other unhandled exceptions 
    Application.ShowException(E); 
end; 

TDBXError是另一個我們的陷阱,因爲這通常意味着發生了DB錯誤,如外鍵或唯一鍵衝突。由於沒有在數據庫中進行更改,因此我們在本地更改了Abort,這使我們與數據庫保持同步。

因爲我們處理與數據庫同步的方式(通過OnBeforePostOnBeforeDelete),沒關係,連接被切斷與用戶重新連接,並且獲得新的DataSnap會話。我們甚至可以重新啓動DataSnap服務器,而無需用戶丟失更改等。他們只需再次登錄並點擊保存。什麼都不會丟失。

所有這些都會回答你的第一個問題......總有一天,我們將實現一種脫機模式,其中TClientDataSet可以保存到用戶的硬盤驅動器,下次他們登錄時,我們將執行同步以應用所有本地保存的更改。但是我們還沒有這樣做 - 所以我對你的第二個問題沒有很好的答案。

+0

你說「用戶可以重新登錄」,但你沒有說你是怎麼做到的?在我自己的Datasnap應用程序中,即使是對TSQLConnection1.Connected:= False的調用,也會引發異常(10053),因爲它試圖告訴服務器(現在不存在)。我在這裏捕捉22。你是怎麼繞過_that_的? – nolaspeaker

+1

@nolaspeaker - 因爲我知道我要重新進行身份驗證,所以我並不在意這個例外。所以我只使用'try sqlcon.Close;除了結尾;',它吃任何例外。然後,我可以靜靜地重新進行身份驗證,或者再次向用戶顯示登錄對話框,以便他們手動登錄。 –

+0

是的,該處理也發生在我身上 - 在我問你問題之後! :-)感謝您的迴應。 – nolaspeaker

相關問題