我刚刚决定解决 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\nRun Code Online (Sandbox Code Playgroud)\n\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;\nRun Code Online (Sandbox Code Playgroud)\n
TADOConnection最好的选择不是破坏内部结构,而是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;
Run Code Online (Sandbox Code Playgroud)
设置ADOConnection1.ConnectionObject := NewConnectionObject会销毁之前的内部对象FConnectionObject并设置一个新的连接对象以供该 TADOConnection对象使用。
此外,您还需要在异常发生时处理特定的 EOleException.ErrorCode(可能的E_FAIL)异常,以便确保您不会处理与您的问题无关的其他异常。
我没有针对您的特定场景(SQL 重新启动)尝试此操作。我将其留给您进行测试。
编辑:使用 SQL Server 2014 和SQLOLEDB.1. 我的应用程序连接到 SQL,重新启动 SQL 后,我无法重现所描述的行为“连接永久断开”。a Close/Open完成了工作,客户端重新连接。