ADOConnection连接SQLServer自动断网问题解决

tzdgg 2014-12-23 02:44:08
Win7上ADO连接SQLServer过几十分钟后自动断网(被防火墙拦截等)问题终于解决了,困惑了很久
今天终于解决了!方法很简单,和大家共享一下。

问题现象:ADO连接SQLServer过几十分钟后(有的过几周)数据库连接无缘无故断开,
再做数据库操作报错“连接失败”。实际上此时数据库服务器可以ping通,
新创建其他ADO控件连接数据库也没问题。就这个ADO不行了。

问题分析:
刚开始想得比较简单,只要创建个线程或者Timer时时判断ADOConnecton1.Active属性=false不得了么。但实际上因为后台原因
或者服务断开再重连、被防火墙拦截等意外情况发生时ADOConnecton1.Active属性仍然是true!无法判断。
后来想到用ping,如果ping不通那就断开了?!但是ping通了未必说明数据库就能连通!ping无法判断数据库能否连通。
那么线程里面不断执行个select GetDate 之类简单SQL,如果失败就判断数据库断开行不行呢?显然不行,
多用户同时不断连接数据库对服务器压力太大了,不可取。
后来网上查了很多材料,有人提出捕获OleException的方法,既不创建线程和定时器判断数据库是否断开,而是当用户执行操作
发生Ole异常时捕获它,如果是数据库连接错误,那么恢复数据库连接即可,我在他们代码基础上完善了一下,以下是实现代码。

控件:

Button1: TButton;
ADOConnection1: TADOConnection;
Button2: TButton;
ADOQuery1: TADOQuery;
DataSource1: TDataSource;
DBGrid1: TDBGrid;
ApplicationEvents1: TApplicationEvents;

代码:

uses ComObj;

{$R *.dfm}

procedure TForm1.ApplicationEvents1Exception(Sender: TObject; E: Exception);
var
I: integer;
begin
//请执行如下命令或者其他方法强制产生数据库连接断开情况,以触发如下异常。
//net stop MsSqlServer
//net start MsSqlServer
if (E is EOleException) and ((E as EOleException).ErrorCode= -2147467259) then
begin
ADOConnection1.Connected := False;
try
ADOConnection1.Connected := True;
except On E2: Exception do
begin
MessageDlg('重连数据库发生错误:'#13 + E2.Message, mtError, [mbOK], 0);
end;
end;
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
sSQL: string;
begin
sSQL:= 'Provider=SQLOLEDB.1;Password=YourPassword;Persist Security Info=True;' +
'User ID=sa;Initial Catalog=YourDatabase;Data Source=.';

with ADOConnection1 do
begin
LoginPrompt:= false;
Connected:= false;
ConnectionString:= sSQL;
Connected:= true;
end;
ShowMessage('ok');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
with ADOQuery1 do
begin
Close;
SQL.Clear;
SQL.Add('select * from Test');
Open;
end;
end;

至于怎么避免数据库频繁断开问题还没有解决,我觉得可能SQLServer或者防火墙可以设置吧,
如果有人知道,请回复邮件:tzdgg@163.com万分感谢!
...全文
2074 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
海宏AA 2016-07-26
  • 打赏
  • 举报
回复
//网络是否还通 function getConnectionConnected(AConn:TAdoConnection):Boolean; var conn:TAdoConnection; err:Error; lNetErr:Boolean; begin conn:=AConn; result:=conn.connected; with conn.errors do try if not result then exit; //未连接 //网络是否断开 result:=not ( (Count>0) and ((Item[0].Number=-2147467259) or (pos('网络',Item[0].Description)>0) or (pos('连接', Item[0].Description)>0)) ); except end; end; //检查网络是否还通着,没通就自动重连 function checkConnectionConnected(AConn:TAdoConnection; lIfDisconnectTryReConnect:Boolean=true):Boolean; label lbl_End; var conn:TAdoConnection; err:Error; lConn, lRe:Boolean; begin conn:=AConn; lRe:=lIfDisconnectTryReConnect; with conn.errors do try result:=conn.connected; lConn:=getConnectionConnected(conn); //网络是否断开 if lConn then goto lbl_End; //网络正常 //处理网络已断开:自动重连 if lRe then try conn.close; conn.open; conn.Errors.Clear; //清空错误 except on x:Exception do ; //x.free end; lbl_End://处理完成 finally result:=conn.connected; end; end;
道玄希言 2014-12-25
  • 打赏
  • 举报
回复
如果只考虑断网的问题, 我们可以假定我们的查询等语句, 平时都是正确的, 一旦出错, 抛出异常时, 不管什么原因, 我们都重连网络一次. 如果网络连接正确, 则再次执行操作.
道玄希言 2014-12-25
  • 打赏
  • 举报
回复
我是直接在查询语句中判断的. procedure TForm1.Button2Click(Sender: TObject); begin try 查询,等操作 except 重连; if ( 如果连接成功) begin try 然后重新执行查询等操作 except 返回错误. end; end; end; end;
不得闲 2014-12-25
  • 打赏
  • 举报
回复
多谢共享,看看系统的安全设置是否有这种阻断,昨天我也是找了半天发现在系统的安全设置中没开放我的程序,结果外面的都无法访问我的电脑上的服务器程序
tzdgg 2014-12-25
  • 打赏
  • 举报
回复
今天和同事讨论了一下,实际上这种情况只要封装一下数据库操作的方法,每次执行select、insert、update、delete前执行个getDate之类简单的SQL,如果网没断那就瞬间正确返回日期,如果没有那就网断了,这个费点时间,就重连网络就行了,不过大部分情况是假断网的情况。SQLServer定期断开的问题普遍存在,所以说到底就是数据库访问没有进行良好封装导致,因为SQL语句太多,没封装的情况下要是每个地方都加个GetDate判断是否断网肯定累死。所以封装有多重要。
lyhoo163 2014-12-25
  • 打赏
  • 举报
回复
还可以采取心跳。定时少流量连接。
固执的大叔 2014-12-25
  • 打赏
  • 举报
回复
谢谢分享,共同进步!我的方法跟你的差不多!
lyhoo163 2014-12-23
  • 打赏
  • 举报
回复
谢谢共享。只有共享,才能共同提高。
tzdgg 2014-12-23
  • 打赏
  • 举报
回复
-2147467259错误代码是网上抄的,你测试一下就知道了,确实返回这个错误代码。 这个判断比较靠谱。
levonsoft 2014-12-23
  • 打赏
  • 举报
回复
if (E is EOleException) and ((E as EOleException).ErrorCode= -2147467259) then 这个靠谱吗? 这个errorcode 代表?? 我以前的做法就是定期访问数据库中的某个表的(其实就是执行一条最简单的sql语句) 如果失败,说明sql 连接异常。需要重连。 active 确实是不靠谱的。

2,497

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 数据库相关
社区管理员
  • 数据库相关社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧