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

Posted

技术标签:

【中文标题】如何检测到 TadoConnection 丢失了与服务器的通信?【英文标题】:How can I detect that a TadoConnection lost the communication with the server? 【发布时间】:2011-01-18 08:33:54 【问题描述】:

我需要检测TAdoConnection 组件何时失去与服务器的连接。我尝试过使用 OnDisconnect 事件,但这只会在调用 Close 方法或 Connected 属性设置为 false 时触发。

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

SELECT 1 RESULT FROM DUAL

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

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

【问题讨论】:

SQL Server 允许使用 SQL.Text = ' ' 作为查询(但不是 '')的 Qry.ExecSQL。这可以每秒执行数百次。 【参考方案1】:

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

那种...

【讨论】:

嗨大软。如果我们在主线程中使用 TADOConnection,我们应该从主线程“ping”sql 吗?我们也应该使用相同的 TADOConnection 还是使用不同的“ping”TADOConnection?【参考方案2】:

@Dimitry 的回答非常好。如果知道连接是否丢失对您的应用程序至关重要,则使用 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】:

我在连接池上有同样的问题。我开发了一个 TADOSQLConnectionPool 类来帮助重用线程数据库工作的连接。当我想为线程分配连接时,我尝试通过将最小作业运行为“选择 1”来检查它的运行状况。这样,我可以确定连接。如果失败,我将处理所有连接以在下次请求时重新创建。

【讨论】:

【参考方案4】:

这是放弃 ADO 并使用 DBX 的原因之一。 Ado 架构是基于服务器游标的,这要求不要在任何时候失去与服务器的连接。如果在某些情况下连接丢失,连接将无法重新建立。另一方面,DBX 由于其断开连接的架构,几乎可以重新连接。

【讨论】:

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

以上是关于如何检测到 TadoConnection 丢失了与服务器的通信?的主要内容,如果未能解决你的问题,请参考以下文章

聊天机器人如何检测人是否加入了与客户的聊天会话?

如何检测丢失的字体字符

如果外部 ADO 连接已连接或断开,如何检测组件内部?

如何检测套接字连接何时丢失?

我可以使用 Python3.6 Sanic 在 websockets 中检测到“连接丢失”吗?

Delphi 的 TADOConnection 线程安全吗?