【问题标题】:Delphi AdoConnection ReconnectDelphi AdoConnection 重新连接
【发布时间】:2016-12-22 10:13:42
【问题描述】:

我刚刚决定解决 MSSQL 数据库服务器重新启动时的“连接”问题,并且连接永远断开。

到目前为止,唯一的解决方案是重新启动程序,但在很远的服务器上并不总是那么容易(并且必须首先检测到问题)。

**下面的代码似乎运行良好,但熟练的 ADO 人员能否更深入地查看代码并查看此代码需要的任何错误/问题或改进? **

Type
  TComponentHelper = class helper for TComponent
     Procedure Reconnect(var AdoConn:TAdoConnection; ConnStr:String);
  end;

procedure TComponentHelper.Reconnect(var AdoConn: TAdoConnection; ConnStr: String);
begin
  if Assigned(AdoConn) then begin
    FreeAndNil(AdoConn);
    AdoConn := TAdoConnection.Create(Self);
    AdoConn.ConnectionString := ConnStr;
    AdoConn.LoginPrompt := false;
    SetConnAdoComponent(Self,AdoConn);
    AdoConn.Open;
  end;
end;

procedure SetConnAdoComponent(aSrc:TComponent; var AdoConn:TAdoConnection);
var
  Ctrl : TComponent;
  i    : Integer;
begin
  if (aSrc = Nil) then Exit;
  if (aSrc.ComponentCount <= 0) then Exit;
  for i:=0 to aSrc.ComponentCount-1 do begin
    Ctrl := aSrc.Components[i];
    if (Ctrl is TAdoQuery) then TAdoQuery(Ctrl).Connection := AdoConn;
    if (Ctrl is TAdoTable) then TAdoTable(Ctrl).Connection := AdoConn;
    if (Ctrl is TAdoDataset) then TAdoDataset(Ctrl).Connection := AdoConn;
  end;
end

我从 TForm 或 TDataModule 中的 Exception 部分调用 Reconnect(),AdoConn 是 TAdoConnection 组件的名称,ConnStr 是使用的完整连接字符串。

Except
  On E:EOleException do begin
    ReConnect(AdoConn,ConnStr);
  end;
  On E:Exception do begin
    ReConnect(AdoConn,ConnStr);
  end;
End;

【问题讨论】:

  • 我认为通过重新连接来处理所有异常有点过于宽泛。当您尝试重新连接到数据库时,您可能会遇到非常奇怪的行为,例如查询错误或内存错误。第二件事是您正在销毁 adoconnection 对象,而其他组件仍在使用它,它甚至可能在您处理异常的过程的被调用者之一中使用。我认为你在这里走错了路。尝试创建您自己的 TAdoConnection 来处理此错误并重新连接。
  • 如果代码有效,这肯定属于 CodeReview stackexchange 站点吗?另外,您是否简单地尝试过CloseOpen 连接?
  • @kobik:像往常一样,您对我的回答非常正确,我已将其删除。谢谢。我以后可能会再去一次。
  • 您确定您描述的“连接”问题永远丢失了吗? SQL Server重启的时候我没有测试,但是不是AdoConn.Close然后AdoConn.Open就解决了问题吗?
  • Craig - 关闭和打开不起作用。它与 OleDB 将连接保留在连接池中(仍然错误)有关。所以破坏 - 创造是一种方式。不知道 CodeReview Stackexchange。

标签: delphi ado


【解决方案1】:

与其破坏TADOConnection,不如用新的TADOConnection.ConnectionObject 替换内部的TADOConnection.ConnectionObject。例如

uses ActiveX, ComObj, ADOInt;

function CreateADOConnectionObject: _Connection;
begin
  OleCheck(CoCreateInstance(CLASS_Connection, nil, CLSCTX_INPROC_SERVER or
    CLSCTX_LOCAL_SERVER, IUnknown, Result));
end;

var
  NewConnectionObject: _Connection;
  ConnectionString: WideString;
begin
  ConnectionString := ADOConnection1.ConnectionString;
  NewConnectionObject := CreateADOConnectionObject;
  NewConnectionObject.ConnectionString := ConnectionString;
  ADOConnection1.Close;
  // set the new connection object
  ADOConnection1.ConnectionObject := NewConnectionObject;
  ADOConnection1.Open;
end;

设置ADOConnection1.ConnectionObject := NewConnectionObject会破坏之前的内部FConnectionObject,并设置一个新的连接对象供TADOConnection对象使用。

您还需要在异常发生时处理特定 EOleException.ErrorCode(可能是E_FAIL),以确保您不处理与您无关的其他异常问题。

我没有在您的特定场景(SQL 重新启动)中尝试此操作。我把它留给你测试。

编辑:使用 SQL Server 2014 和 SQLOLEDB.1 测试。我的应用程序连接到 SQL,并且在重新启动 SQL 后,我无法重现所描述的行为 “连接永久断开”Close/Open 完成了这项工作,客户端重新连接。

【讨论】:

  • 在您的编辑中,我得到了相同的结果;甚至杀死 sqlserver 进程。 OP 必须做一些与我们有很大不同的事情,以使 Close / Open 不起作用。
猜你喜欢
  • 1970-01-01
  • 2018-07-11
  • 2012-03-15
  • 2019-08-22
  • 1970-01-01
  • 1970-01-01
  • 2014-02-14
  • 2010-09-20
  • 2010-12-26
相关资源
最近更新 更多