如何在整个应用程序中恢复/重试损坏的TADOConnection?

时间:2015-06-24 10:47:04

标签: database delphi delphi-7 adodb

我有一个全局TADOConnection的数据模块(默认KeepConnection设置为true)。 我现有的应用程序中有许多数据集和查询使用此全局TADOConnection

我想知道是否有一些聪明的方法可以在短暂的网络断开的情况下恢复/重试ado连接? (这种情况有时发生在连接不稳定的客户身上)。

很容易重现我的需要。只需在启动时打开TADOConnection即可。打开一些TADODataSet,然后禁用并启用您的"本地连接"。如果您尝试刷新数据集,则会引发EOleException异常

  

"连接失败"

  

" [DBNETLIB] [ConnectionWrite(send())。]一般网络错误。校验   您的网络文档"

如果我重启应用程序一切都很好。

网络断开连接时TADOConnection没有触发任何事件。 TADOConnection.Connected仍为true

当然,我可以为每个TDataSet.OpenExecute使用try / catch,但我正在寻找一些"集中式"我的大型应用的解决方案。 所以如果"连接失败"我可以知道哪个数据集正在尝试打开,然后重试。

2 个答案:

答案 0 :(得分:1)

在网络断开连接时永远不会触发。但是你可以在每个命令之前检查连接。因此,如果AdoConnection断开连接,您可以在此之后重新连接并执行命令。

如果你想集中解决方案并且你有1个连接,你可以这样做;

Const
  ConnectionTestString=' '; //Yes, it's work on Sql Server. If doesnt your db, you can use 'Select 1'

程序;

Procedure TDM.GetCommandResult_Conn(CText:String;Connection : TAdoConnection);
var Ado_Ds_Tmp:TAdoCommand;
Begin
    Ado_Ds_Tmp:=TAdoCommand.Create(self);
    try
      Ado_Ds_Tmp.Connection:=Connection;
      Ado_Ds_Tmp.ParamCheck := False;
      Ado_Ds_Tmp.CommandText:=CText;
      try
        Ado_Ds_Tmp.Execute;
      except
        DM.RaiseExceptionCreate('Error ! Command, ('+StrToList(CText, ' ')[0]+')');
      end;
    finally
      Ado_Ds_Tmp.Destroy;
    end;
end;

procedure TDM.ADOConnection1WillExecute(Connection: TADOConnection;
  var CommandText: WideString; var CursorType: TCursorType;
  var LockType: TADOLockType; var CommandType: TCommandType;
  var ExecuteOptions: TExecuteOptions; var EventStatus: TEventStatus;
  const Command: _Command; const Recordset: _Recordset);
var
   ErrorLogFileName : string;
   ErrorFile : TextFile;
   ErrorData : string;
   Msg : String;
begin
  try
    if (CommandText<>ConnectionTestString) then begin
      DM.GetCommandResult_Conn(ConnectionTestString, Connection);
    end;
  except
    try
      try
        Connection.Connected := False;
      except
      end;
      try
        Connection.ConnectionString := AdoConnectionString;
        Connection.Mode:=cmShareDenyNone;
      finally
        try
          Connection.Connected := True;
          // If you wanna log for frequency 
          ErrorLogFileName := ChangeFileExt(Application.ExeName,'.error.log');
          AssignFile(ErrorFile, ErrorLogFileName);
          if FileExists(ErrorLogFileName) then
            Append(ErrorFile)
          else
            Rewrite(ErrorFile);
          try
            ErrorData := Format('%s : %s : %s (%s / %s)',[DateTimeToStr(Now), 'Disconnected but we reconnect.', '', 'UserName : '+DBUser, 'Client : '+GetComputerNetName]);
            WriteLn(ErrorFile,ErrorData);
          finally
            CloseFile(ErrorFile)
          end;
        except
          DM.RaiseExceptionCreate('ReConnection Failed!');
        end;
      end;
    except
    end;
  end;
end;

有问题吗?

答案 1 :(得分:0)

这个想法可能是捕获连接错误然后通过重试来管理它。 建议:

此函数返回异常描述

function GetStrException(ExceptObject: TObject; ExceptAddr: Pointer):String;
var
  Buffer: array[0..1023] of Char;
begin
    ExceptionErrorMessage(ExceptObject, ExceptAddr, Buffer, SizeOf(Buffer));
    Result:=Buffer;
end;

这是一个简单的测试想法!

procedure TForm1.Button2Click(Sender: TObject);
var
 s,error:String;
begin
 //a select as an example
 S := 'SELECT COUNT(*) FROM MyTable';
 TRY
   WITH ADOQuery1 DO BEGIN SQL.Clear; SQL.Add(s);OPEN;END;
   Memo1.Lines.ADD(ADOQuery1.Fields[0].AsString);
 EXCEPT
   error:=(GetStrException(ExceptObject,ExceptAddr));
   //using MySql my error case is when the connection is lost, so the error is "Server has gone away"
   if pos(error,'has gone away')>0 then
     begin
       Showmessage('Connection Error, please try again');
       try
          sleep(1000)
          AdoConnection1.close;
          AdoConnection1.open;
       except
         Showmessage('The connection Error persists, please contact the support');
       end;
     end;
 END;
end;

一个好的解决方案是集中插入/更新和选择过程,然后 捕捉错误并尝试之前调整一两次情况 向用户显示消息