Delphi连接重新连接

Delphi连接重新连接,delphi,ado,Delphi,Ado,我刚刚决定在MSSQL数据库服务器重新启动时解决“连接”问题,并且连接会永久断开 到目前为止,唯一的解决方案是重新启动程序,在很远的服务器上并不总是那么容易(而且必须首先检测到问题) **下面的代码似乎工作得很好,但是熟练的ADO人员是否可以更深入地查看代码,并查看此代码所需的任何错误/问题或改进** Type TComponentHelper = class helper for TComponent   Procedure Reconnect(var AdoConn:TAdoCon

我刚刚决定在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中的异常部分调用Reconnect(),ADOCON是TAdoConnection组件的名称,ConnStr是使用的完整connectionstring

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

与其销毁
TADOConnection
,最好的选择是将内部
TADOConnection.ConnectionObject
替换为新的。e、 g

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
将销毁以前的内部
fcconnectionobject
,并设置一个新的连接对象供
TADOConnection
对象使用

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

我没有在您的特定场景(SQL重启)中尝试这一点。我让你来测试


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

我认为通过重新连接来处理所有异常有点过于广泛。当您尝试重新连接到数据库时,例如在查询错误或内存错误中,可能会出现非常奇怪的行为。第二件事是,您正在销毁adoconnection对象,而其他组件仍在使用它,它甚至可能在处理异常的过程的一个被调用方中使用。我认为你在这里走错了路。请尝试创建您自己的TAdoConnection来处理此错误并可以重新连接。如果代码正常工作,这肯定属于CodeReview stackexchange站点吗?另外,你是否简单地尝试了
关闭
打开
连接?@kobik:像往常一样,你对我的答案很正确,我已经删除了。谢谢我以后可能会再来一次。你确定你所描述的“连接”问题会永远消失吗?当SQL Server重新启动时,我没有测试它,但它不是一个
AdoConn.Close
,然后
AdoConn.Open
解决了问题?Craig-Close and Open不起作用。这与OleDB将连接保持在连接池中有关(仍然存在错误)。所以销毁-创建是一种方法。不知道CodeReview Stackexchange。在您的编辑中,我得到了相同的信息;甚至杀死sqlserver进程。OP必须做一些与我们明显不同的事情,才能使
Close
/
Open
不起作用。