我刚刚决定解决 MSSQL 数据库服务器重新启动时的“连接”问题,并且连接会永远断开。
\n\n到目前为止,唯一的解决方案是重新启动\xc2\xa0程序,这在遥远的服务器上并不总是那么容易(并且必须首先检测到问题)。
\n\n**下面的代码似乎工作正常,但是熟练的 ADO 人员能否更深入地研究代码并发现此代码是否有任何错误/问题或需要改进?**
\n\nType\n  TComponentHelper = class helper for TComponent\n\xc2\xa0    Procedure Reconnect(var AdoConn:TAdoConnection; ConnStr:String);\n\xc2\xa0 end;\n\nprocedure TComponentHelper.Reconnect(var AdoConn: TAdoConnection; ConnStr: String);\nbegin\n\xc2\xa0 if Assigned(AdoConn) then begin\n\xc2\xa0 \xc2\xa0 FreeAndNil(AdoConn);\n  \xc2\xa0 AdoConn := TAdoConnection.Create(Self);\n\xc2\xa0   AdoConn.ConnectionString := ConnStr;\n\xc2\xa0 \xc2\xa0 AdoConn.LoginPrompt := false;\n  \xc2\xa0 SetConnAdoComponent(Self,AdoConn);\n\xc2\xa0   AdoConn.Open;\n\xc2\xa0 end;\nend;\n\nprocedure SetConnAdoComponent(aSrc:TComponent; var AdoConn:TAdoConnection);\nvar\n  Ctrl : TComponent;\n  i    : Integer;\nbegin\n  if (aSrc = Nil) then Exit;\n  if (aSrc.ComponentCount <= 0) then Exit;\n  for i:=0 to aSrc.ComponentCount-1 do begin\n    Ctrl := aSrc.Components[i];\n    if (Ctrl is TAdoQuery) then TAdoQuery(Ctrl).Connection := AdoConn;\n    if (Ctrl is TAdoTable) then TAdoTable(Ctrl).Connection := AdoConn;\n    if (Ctrl is TAdoDataset) then TAdoDataset(Ctrl).Connection := AdoConn;\n  end;\nend\n我从 TForm 或 TDataModule 中的异常部分调用 Reconnect(),AdoConn 是 TAdoConnection 组件的名称,ConnStr 是使用的完整连接字符串。
\n\nExcept\n  On E:EOleException do begin\n    ReConnect(AdoConn,ConnStr);\n  end;\n  On E:Exception do begin\n    ReConnect(AdoConn,ConnStr);\n  end;\nEnd;\nTADOConnection最好的选择不是破坏内部结构,而是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 后,我无法重现所描述的行为“连接永久断开”。a Close/Open完成了工作,客户端重新连接。