我有一个全局TADOConnection
的数据模块(默认KeepConnection
设置为true)。
我现有的应用程序中有许多数据集和查询使用此全局TADOConnection
。
我想知道是否有一些聪明的方法可以在短暂的网络断开的情况下恢复/重试ado连接? (这种情况有时发生在连接不稳定的客户身上)。
很容易重现我的需要。只需在启动时打开TADOConnection
即可。打开一些TADODataSet
,然后禁用并启用您的"本地连接"。如果您尝试刷新数据集,则会引发EOleException
异常
"连接失败"
或
" [DBNETLIB] [ConnectionWrite(send())。]一般网络错误。校验 您的网络文档"
如果我重启应用程序一切都很好。
网络断开连接时TADOConnection
没有触发任何事件。 TADOConnection.Connected
仍为true
当然,我可以为每个TDataSet.Open
或Execute
使用try / catch,但我正在寻找一些"集中式"我的大型应用的解决方案。
所以如果"连接失败"我可以知道哪个数据集正在尝试打开,然后重试。
答案 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;
一个好的解决方案是集中插入/更新和选择过程,然后 捕捉错误并尝试之前调整一两次情况 向用户显示消息