断网后如何重新连接

xuxugr 2009-06-10 08:49:34
data module的oncreate事件中

procedure TData1.DataModuleCreate(Sender: TObject);
var filename:string;
begin
filename:=ExtractFilePath(paramstr(0))+'myini.ini';
myinifile:=TInifile.Create(filename);
version:=myinifile.ReadString('ServerInfo','version','');
ADOConnection1.ConnectionString:= 'Provider=SQLOLEDB.1;Password='+myinifile.readstring('ServerInfo','SQLPwd','')+';Persist Security Info=True;User ID='+myinifile.readstring('ServerInfo','SQLUserID','')+';Initial Catalog='+myinifile.readstring('ServerInfo','SQLDBName','')+';Data Source='+myinifile.readstring ('ServerInfo','ServerIP','');
end;

窗体中U_ygbm 的刷新代码

adoquery1 (连接上面的ADOConnection1)
with adoquery1 do
begin
close;
sql.Clear;
sql.Add('select * from tba_ygbm');
open;
end;


在进销存中如果网线断网后再刷新会提示连接失败,如果网络正常后也要退出整个程序后才能再进入操作,刷新也没用
有些程序可以实现重新连接,如何实现呢
...全文
1214 29 打赏 收藏 转发到动态 举报
写回复
用AI写文章
29 条回复
切换为时间正序
请发表友善的回复…
发表回复
ahhjgh 2009-06-16
  • 打赏
  • 举报
回复
我提供的解决方案里面的timer2,timer3都是我的系统的业务逻辑,你不必关心
ahhjgh 2009-06-16
  • 打赏
  • 举报
回复
使用IPWORKS 控件实现PINGSERVER函数
function TForm2.PingServer(ServerIp:string):boolean;
begin
Result := True;
ipwPing1.Timeout := 1;
Try
ipwPing1.PingHost(ServerIp);
Except
Result := False;
end;
end;
xuxugr 2009-06-15
  • 打赏
  • 举报
回复
呵呵!好像没那么简单,因为在保存时比较理想的做法时保存时如果断线就会延迟10秒再执行,直到保存为止,除非退出
lishan200012 2009-06-15
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 xuxugr 的回复:]
data module没有time事件呀,难道在进入系统的主窗体再做一个
[/Quote]
加一个timer控件.
xuxugr 2009-06-14
  • 打赏
  • 举报
回复
我就不相信delphi没有好的解决方法吗
ITlover 2009-06-13
  • 打赏
  • 举报
回复
to ahhigh

你说的是正确的,关键我们还可以在判断断了之后,可以关闭TIMER.连通后,可以重开TIMER.这样做是不会浪费资源的.最多浪费最初的判断时间5秒.

 另外,请允许我提出一点疑问:你的方法是尝试PING通服务器的IP,假如数据库安装在本机,而且是本机的数据库发生问题了呢?

ahhjgh 2009-06-13
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 ITlover 的回复:]
这人问题其实挺普遍的,我们也应考虑断线是断在了数据库出问题,还是断在网络上;数据库是装在本机还是在网络服务器中;所以PING地址,查端口是一种方法(XP不装补丁?),我使用了几种方法之后,最后回归还是用SQL语句来解决问题(要求是判断断线响应时间尽量短),这里,把我的做法提出来,大家讨论一下,也给我点补充.
1.先建一个测试是否正常连接SQL的函数
function canlink:boolean;//(这种方法,如果断了,响应时间大概是5秒左右)
var …
[/Quote]
这个方法比较耗费资源,并且会造成假死现象,因为:
1、当网络正常时,这种方法还是会频繁查询数据库,造成资源浪费;
2、当网络断开时,该方法会造成假死现象,首先调用canlink时,因为网络不通,会有延时等待,并且必定返回FALSE,这时又会去重连数据库,又会造成更大的延时等待。检测、重连循环进行,不断的假死,直到网络正常为止
ahhjgh 2009-06-13
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 ZuoBaoquan 的回复:]
@xuxugr, @ahhjgh
只要不采用异步连接/执行,ADO超时的情况就无法避免。你可以根据网络情况适当调整ConnectionTimeout和CommandTimeout的值。
[/Quote]
在KEEPCONNECTION=TRUE的情况下,Connected属性永远为TRUE,即使网络已断开1年也是一样,所以通过设置TIMEOUT属性的方法不可用
ITlover 2009-06-13
  • 打赏
  • 举报
回复
这人问题其实挺普遍的,我们也应考虑断线是断在了数据库出问题,还是断在网络上;数据库是装在本机还是在网络服务器中;所以PING地址,查端口是一种方法(XP不装补丁?),我使用了几种方法之后,最后回归还是用SQL语句来解决问题(要求是判断断线响应时间尽量短),这里,把我的做法提出来,大家讨论一下,也给我点补充.
1.先建一个测试是否正常连接SQL的函数
function canlink:boolean;//(这种方法,如果断了,响应时间大概是5秒左右)
var
trylinkado:tadoquery;
begin
result:=False;
trylinkado:=tadoquery.Create(nil);
testlinkconnectstring:='Provider=SQLOLEDB.1;Password='+LogPass+';Persist Security Info=True;User ID='+LogUser+';Initial Catalog='+Database+';Data Source='+ServerName+';connect timeout=2;Use Procedure for Prepare=1;Auto Translate=True;Packet Size=4096;Workstation ID='+ServerName+';Use Encryption for Data=False;Tag with column collation when possible=False';

trylinkado.ConnectionString:=testlinkconnectstring;
//请务必加上connect timeout,以加快响应速度
trylinkado.CommandTimeout:=2;
try
trylinkado.SQL.Add('select 1 "nettest"');
trylinkado.Open;
trylinkado.Close;
Result:=True;
except
Result:=false;
end;
trylinkado.Free;
end;

2.加入一个TIMER,定时检测是否断了(调用canlink),如果断了,给用户一个提示,让他重连

3.重连后的处理
A.如果你用的是动态ADOQUERY,那么重连成功后就可以直接使用了
B.如果你的ADOQUERY跟了一个ADOConnection,我是这样做的
try
DM.ADOConnection1.Execute('select 1 "nettest"');
except
if dm.ADOConnection1.Connected=True then dm.ADOConnection1.Connected:=False;
dm.ADOConnection1.Connected:=True;
try
DM.ADOConnection1.Execute('select 1 "nettest"');
except
;
end;
end;
C.如果你的ADOQUERY直接使用ConnectionString,好象没招(哪位有办法,也贴出告知一声吧)
4.如果你当前的进程还要控制其它进程,并通知断线和恢复,以及做相关处理,我是用广播消息来做的
yanele 2009-06-13
  • 打赏
  • 举报
回复
路过,学习!
ahhjgh 2009-06-13
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 xuxugr 的回复:]
引用 12 楼 ahhjgh 的回复:
引用 11 楼 xuxugr 的回复:
引用 10 楼 ZuoBaoquan 的回复:
这个问题确实存在,主要是因为KeepConnection设为True的时候,ADOConnection会“尝试”保持数据库连接,但是碰到连接失败或网络问题的时候Connected仍未True,导致以后一直连接不上(报错)。

解决方法:
在OnExecuteComplete事件中判断Error是否为ahhjgh说的那些错误码,如有则显示调用Connection.Close方法,并可考虑在此处尝试…
[/Quote]
几秒检测一次,因为重连之前,我是先PING服务器的,如果不通的话,就不会去打开ADOCONNECTION,所以不会耗费服务器资源的,也基本不耗费客户端资源,整个过程不会产生检测延时,造成假死的现象
xuxugr 2009-06-13
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 ahhjgh 的回复:]
这个问题我也碰到过,最后是这么解决的,检测过程贴出,你自己参考:
procedure TForm2.Timer4Timer(Sender: TObject);
var
strError:string;
ConnStr,ServerIp:string;
tmpStrList :TStringList;
Const
CONNECTABORT_SQLSERVER1 = '08S0 '; //连接失败的错误号(SQLSERVER) 在简体版本下,显示不出最后一位
CONNECTABORT_SQLSERVER2 = '08S01'; //连接失败的错误号(SQLSERVER)
CONNECTFAULT_SQLSERVER…
[/Quote]

ahhjigh

你能把form1,form2里的源代码全部发给我吗,麻烦你了,我是新手
gr.xu@yahoo.com.cn
ZuoBaoquan 2009-06-13
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 ahhjgh 的回复:]
引用 13 楼 ZuoBaoquan 的回复:

@xuxugr, @ahhjgh
只要不采用异步连接/执行,ADO超时的情况就无法避免。你可以根据网络情况适当调整ConnectionTimeout和CommandTimeout的值。

在KEEPCONNECTION=TRUE的情况下,Connected属性永远为TRUE,即使网络已断开1年也是一样,所以通过设置TIMEOUT属性的方法不可用
[/Quote]

当数据库连接成功后,如果KeepConnection=True,那碰到连接断开时Connected属性仍未True。这个时候可以在OnExecuteComplete里面可以调用Close把Connection关闭。我的意思是根据网络情况适当调整ConnectionTimeout和CommandTimeout的值,来减少超时时间。这对于采用同步连接的ADO来说,永远无法避免,使用Timer也是如此。
xuxugr 2009-06-13
  • 打赏
  • 举报
回复
data module没有time事件呀,难道在进入系统的主窗体再做一个
xuxugr 2009-06-13
  • 打赏
  • 举报
回复
头痛,没人知道吗
xuxugr 2009-06-12
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 ZuoBaoquan 的回复:]
这个问题确实存在,主要是因为KeepConnection设为True的时候,ADOConnection会“尝试”保持数据库连接,但是碰到连接失败或网络问题的时候Connected仍未True,导致以后一直连接不上(报错)。

解决方法:
在OnExecuteComplete事件中判断Error是否为ahhjgh说的那些错误码,如有则显示调用Connection.Close方法,并可考虑在此处尝试自动连接。

楼主可以试试。
[/Quote]


现是是可以了,首选会提示连接失败,我刷新会提示连接超时,再确定就连上去了,但是太耗时间了
ZuoBaoquan 2009-06-12
  • 打赏
  • 举报
回复
这个问题确实存在,主要是因为KeepConnection设为True的时候,ADOConnection会“尝试”保持数据库连接,但是碰到连接失败或网络问题的时候Connected仍未True,导致以后一直连接不上(报错)。

解决方法:
在OnExecuteComplete事件中判断Error是否为ahhjgh说的那些错误码,如有则显示调用Connection.Close方法,并可考虑在此处尝试自动连接。

楼主可以试试。
shuihan20e 2009-06-12
  • 打赏
  • 举报
回复
不需要吧
如果与数据库的连接断开了,你再执行OPEN或EXECSQL时,会自动连接数据库的
阿三 2009-06-12
  • 打赏
  • 举报
回复
在执行操作前,判断一下adoconnection是否联接正常。
ahhjgh 2009-06-12
  • 打赏
  • 举报
回复
这个问题我也碰到过,最后是这么解决的,检测过程贴出,你自己参考:
procedure TForm2.Timer4Timer(Sender: TObject);
var
strError:string;
ConnStr,ServerIp:string;
tmpStrList :TStringList;
Const
CONNECTABORT_SQLSERVER1 = '08S0 '; //连接失败的错误号(SQLSERVER) 在简体版本下,显示不出最后一位
CONNECTABORT_SQLSERVER2 = '08S01'; //连接失败的错误号(SQLSERVER)
CONNECTFAULT_SQLSERVER = '08001'; //连接不上服务器的的错误号(SQLSERVER)
begin
if Form1.ADOConnection1.Errors.Count >0 then
begin
strError := Form1.ADOConnection1.Errors.Item[0].SQLState;
if (strError = CONNECTABORT_SQLSERVER1)or(strError = CONNECTABORT_SQLSERVER2)or(strError = CONNECTFAULT_SQLSERVER) then
begin
Timer2.Enabled := false;
Timer3.Enabled := false;

ConnStr := Form1.ADOConnection1.ConnectionString;
tmpStrList := Common.SplitString(ConnStr,';');
ServerIp := tmpStrList.Values['Data Source'];
tmpStrList.Free;

if PingServer(ServerIp) then
begin
Form1.ADOConnection1.Connected := false;
Try
Form1.ADOConnection1.Open;
Timer2.Enabled := true;
Timer3.Enabled := true;
Except
end;
end;
end;
end;
end;
加载更多回复(9)

2,497

社区成员

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

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