问题 如何检测到TadoConnection丢失了与服务器的通信?


我需要检测一下 TAdoConnection 组件已丢失与服务器的连接。我试过用过 OnDisconnect 事件但仅在调用Close方法或Connected属性设置为false时触发。

我尝试过的另一个选择是使用 TTimer 并执行这样的查询

SELECT 1 RESULT FROM DUAL

在OnTimer事件中,捕获发生的任何异常。

有没有更好的选择来检测连接丢失?


9846
2018-02-18 14:27


起源

SQL Server允许Qry.ExecSQL使用SQL.Text =''作为查询(但不是'')。这可以每秒执行数百次。 - Gerry Coll


答案:


我看到了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可能处于失败状态,因此连接关闭可能引发异常。

有点......


11
2018-02-18 15:39



嗨da-soft。如果我们在主线程中使用TADOConnection应该从主线程“ping”sql吗?我们也应该使用相同的TADOConnection或使用不同的“ping”TADOConnection吗? - zig


@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;

最好的祝福。


3
2018-02-18 20:21





我在连接池上遇到同样的问题。我开发了一个TADOSQLConnectionPool类来帮助重用DB连接的线程连接。当我想为一个线程分配连接时,我试图通过运行最小作业“选择1”来检查它的健康状况。通过这种方式,我将确定连接。如果失败,我将处置所有连接以在下一个请求时重新创建。


0
2018-03-16 04:52





这是放弃ADO并使用DBX的原因之一。 Ado架构是基于服务器游标的,这个requeris不会随时丢失与服务器的连接。如果在某些情况下连接丢失,则连接将无法再次启动。另一方面,由于其断开连接,DBX能够重新连接到永远。


-1
2018-02-18 23:51



这不是真的。 ADO可以用作服务器作为客户端游标,并允许应用断开连接的数据集模型。来自about.com:为了创建断开连接的ADO记录集,必须首先将ADODataSets CursorLocation属性设置为“clUseClient”。然后打开Recordset。然后将ADODatasets Connection设置为Nil。不要关闭ADODataset。 - da-soft
是的ADO可以在公文包模式下工作。但是DBX对这个问题的反应更加自然和可预测。 - Francis Lee