2012-12-12 136 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

相关问题