delphi - 通过客户端-服务器断开连接管理 SQLConnection/Datasnap

标签 delphi delphi-xe2 sqlconnection datasnap disconnect

在我的 Datasnap 客户端应用程序中,我使用 1 个 TSQLConnection 作为我的方法和 ProviderConnection。

当连接丢失时就会出现问题。 TSQLConnection.Connected 和 TSQLConnection.ConnectionState 都没有捕获到这一点。

当我的 TSQLconnection 打开,但我失去了互联网连接,或者服务器停止 Datasnap 客户端应用程序时,会出现很多错误。 (服务器方法或客户端数据集)

我创建了一个函数来管理我的服务器方法的 SQL 连接。但当例如关闭通过 TDSProviderConnection 连接的 ClientDataset 时,会出现更多问题。

问:如何管理客户端应用程序以安全地捕获 TSQL 连接上的任何断开连接。
:您如何管理停机时间,以及如何处理未保存的客户端状态。

停机后重新连接不是问题。

调用服务器方法时:这会抛出异常。

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

因此,我编写了下一个方法,以使用虚拟方法从我的数据模块获取 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;

我以这种方式编写方法,因为找出连接是否丢失的唯一方法是通过虚拟方法,这会引发相同的错误...然后我可以查询重新连接或关闭程序。

编辑:我期待某种一般性答案和指南、该做和不该做的事情。不是对我的代码的更正,这只是为了展示我现在正在做的事情。

最佳答案

我们遇到了同样的问题——如何检测连接何时被切断,以及如何优雅地重新连接。这就是我们最终所做的事情,事实证明这对我们来说非常成功。

我们的用户连接到 DataSnap 服务器来检索数据并进行更改。所有记录的创建、更新和删除都会通过 TClientDataSet 中的 OnBeforePostOnBeforeDelete 事件处理程序立即馈送到数据库。

由于在尝试与服务器通信并发现连接已断开之前,您无法检测客户端何时与 DataSnap 服务器强制断开连接,因此我们添加了一个 TApplicationEvents 来我们的应用程序中的主窗体,并为 OnException 事件编写了一个事件处理程序。当我们看到 EIdSocketError 时,我们知道连接已断开,因此我们向用户显示一条消息,说明同样的情况,然后调用 Abort 以便 Post Delete 在本地数据集中不会发生。用户可以重新登录,然后再次单击保存删除来完成之前的操作。

我们的全局异常处理程序看起来像这样:

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 是我们捕获的另一个错误,因为它通常意味着发生了数据库错误,例如外键或唯一键违规。由于更改不是在数据库中进行的,因此我们在本地中止更改,这使我们与数据库保持同步。

由于我们处理与数据库同步的方式(通过 OnBeforePostOnBeforeDelete),连接被切断和用户重新连接并不重要获取新的 DataSnap session 。我们甚至可以重新启动 DataSnap 服务器,而用户不会丢失所做的更改等。他们只需再次登录并单击保存即可。一切都不会丢失。

所有这些都回答了您的第一个问题...有一天,我们将实现离线模式,其中 TClientDataSet 可以保存到用户的 HDD,并且下次登录时,我们将执行同步以应用所有本地保存的更改。但我们还没有这样做——所以我对你的第二个问题没有一个好的答案。

关于delphi - 通过客户端-服务器断开连接管理 SQLConnection/Datasnap,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13844220/

相关文章:

delphi - ClientDataSet 上的 Order by 不起作用

delphi - dcc32警告UnloadProcs.pas(59):W1035函数“GetType”的返回值可能未定义

delphi - TVirtualStringTree - 单击所选行的任何区域时如何启用拖动?

delphi - DUnit:如何运行测试?

delphi - RTL 和 VCL 内存泄漏

c# - 我怎样才能真正关闭一个sql连接

c# - 公共(public)密封类 SqlConnection : DbConnection, ICloneable

delphi - 是否可以让属性的读/写具有不同的可见性?

delphi - 在 Delphi 中包装函数调用泛型

c# - 使用参数化连接时是否需要关闭连接