当前位置:Gxlcms >
数据库问题 >
Delphi:ADOConnection连接SQLServer自动断网问题解决
Delphi:ADOConnection连接SQLServer自动断网问题解决
时间:2021-07-01 10:21:17
帮助过:24人阅读
untMain;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
IniFiles, ExtCtrls, DB, ADODB,ActiveX;
type
TFrmMain =
class(TForm)
Timer2: TTimer;
procedure FormClose(Sender: TObject;
var Action: TCloseAction);
procedure FormShow(Sender: TObject);
procedure Timer2Timer(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
procedure getXXData();
end;
//ADO连接获取数据线程
TAdoThread =
class(TThread)
protected
procedure execute;
override;
end;
var
FrmMain: TFrmMain;
ConString: string;
{ 初始化临界区CS变量 }
CS: TRTLCriticalSection;
implementation
uses untabout;
{$R *.dfm}
{ TForm1 }{ 写程序异常日志 }
procedure write_error_log(str:
string);
var
F: TextFile;
mfile: string;
begin
try
//判断保存日志文件的目录是否存在
if not DirectoryExists(ExtractFilePath(ParamStr(
0)) +
‘log‘)
then
MkDir(ExtractFilePath(ParamStr(0)) +
‘log‘);
//按日期及时间设定保存日志的文件名
mfile := ExtractFilePath(ParamStr(
0)) +
‘log\ErrLog_‘ + formatdatetime(
‘yyyy-mm-dd‘, now) +
‘.txt‘;
AssignFile(F,mfile);
if not FileExists(mfile)
then
Rewrite(F);//如果文件不存在,则创建一个新的文件,并写入
Append(F);
//追加写入
Writeln(F,str);
//写入并换行
CloseFile(F);
except
end;
end;
procedure TFrmMain.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
{ 清除线程CS变量 }
DeleteCriticalSection(CS);
Timer2.Enabled :=
False;
end;
procedure TFrmMain.FormShow(Sender: TObject);
var
clientini: TIniFile;
db_server,user,password:string;
begin
{ 获取ini配置信息}
clientini := TIniFile.
Create(
‘.\config.ini‘);
try
if clientini<>
nil then
begin
db_server := trim(clientini.readString(
‘database‘,
‘db_server‘,
‘‘));
user := trim(clientini.readString(
‘database‘,
‘user‘,
‘sa‘));
password := trim(clientini.readString(
‘database‘,
‘password‘,
‘‘));
ConString :=
‘Provider=SQLOLEDB.1;Persist Security Info=False;User ID=‘
+user+
‘;Password=‘+password+
‘;Initial Catalog=Testdb;Data Source=‘+
db_server;
end;
finally
clientini.Free;
end;
InitializeCriticalSection(CS);//初始化线程临界区
end;
procedure TFrmMain.Timer2Timer(Sender: TObject);
begin
Timer2.Enabled :=
False;
TAdoThread.Create(False);
end;
procedure TFrmMain.getXXData();
var
ADOStoredProc1: TADOStoredProc;
begin
ADOStoredProc1 := TADOStoredProc.
Create(
nil);
//动态创建ADO控件
try
try
ADOStoredProc1.ConnectionString := ConString;
//采用独立的连接字符串
if ADOStoredProc1.Active
then
ADOStoredProc1.Active :=
false;
ADOStoredProc1.ProcedureName :=
‘GetData‘;
ADOStoredProc1.Prepared :=
false;
ADOStoredProc1.Parameters.Refresh;
ADOStoredProc1.Prepared :=
true;
ADOStoredProc1.ExecProc;
except
on E:Exception do
begin
write_error_log(FormatDateTime(
‘yyyy-mm-dd hh:nn:ss‘,Now)
+
‘>> 执行getXXData时发生异常!错误原因:‘+
E.Message
);
end;
end
finally
ADOStoredProc1.Free;
end;
end;
{ TAdoThread }
procedure TAdoThread.execute;
begin
inherited;
FreeOnTerminate := True;
//设置线程执行完成后自动释放
{进入线程临界区}
EnterCriticalSection(CS);
try
CoInitialize(nil);
//线程中使用ADO,必须调用(需Uses ActiveX)
{读取HIS数据}
FrmMain.getHisData(FrmMain.hasCharge);
CoUninitialize;
finally
{ 离开线程临界区 }
LeaveCriticalSection(CS);
end;
FrmMain.Timer2.Enabled :=
True;
end;
end.
============================
其他解决方法:未验证,资料来自:
http://bbs.csdn.net/topics/390958648
============================
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;
Delphi:ADOConnection连接SQLServer自动断网问题解决
标签:必须 字符 关闭 变量 推荐 res init class you