ADO是线程安全级的,为什么我在多个线程中访问数据库会出现“对象已打开”错误。

Atomictry 2003-09-14 01:52:53
我是用Socket服务端访问数据库时出的错,用的是TServerSocket线程阻塞模式。
请做过此项工作的朋友帮帮忙。
...全文
214 24 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
thingking 2003-09-24
  • 打赏
  • 举报
回复
MARK
Atomictry 2003-09-19
  • 打赏
  • 举报
回复
解决方法是sncel(地狱情人-杨勇) 给了我他调试的工程文件。
Atomictry 2003-09-19
  • 打赏
  • 举报
回复
先感谢sncel(地狱情人-杨勇) 、空心菜、yesry(噎死你),还有其他朋友。

再把问题整理一下:

问题症状:
环境:Windows2000;SQL Server;BCB6.0;
在TServerSocket线程阻塞方式下,线程中可以进行更新,插入。但查询时就可能
会出现如下错误:
“对象已打开”、“[Microsoft][ODBC SQL Server Driver]连接占线导致
另一个hstmt.”、“在异步运行时,操作不能被执行”。

解决问题的方法:
1.在线程中用new方法创建TADOQuery组件。
2.这是最主要的原因:是否用的是for SQL Server驱动,如果用了OLE DB for
ODBC,即使用new创建也会出现连接占线错误。
Atomictry 2003-09-18
  • 打赏
  • 举报
回复
up.

朋友们,我算是被ADO打败了。

现在我只想让DBGrid能够刷新更新显示,除了用ADOQuery查询一遍数据库外,
还有什么方法实现显示当前表数据。
yesry 2003-09-18
  • 打赏
  • 举报
回复
void __fastcall TServerFrm::UpdateField(String updatefield,String updatevalue,String sourcefield,String sourcevalue)
//说明:updatefield为需要更新的字段,updatevalue为需要更新的字段值
// sourcefield为已知字段,updatevalue为已知字段值,如上面的RemoteHostIP
{
String Updatesql="update LinkRecord set "+updatefield;

Updatesql+= "='"+updatevalue+"' where "+sourcefield;

Updatesql+= "='"+sourcevalue+"'";

TADOQuery *q=new TADOQuery(ADOConnection1);
q->Connection=ADOConnection1;//各个线程可以间接公用ADOConnection1,但是ADOQuery不能共享访问
q->CommandText=Updatesql;
q->ExecSQL();//不要用Open();
delete q;
}
sncel 2003-09-18
  • 打赏
  • 举报
回复
联系我:QQ:6522203 MSN:sncel@vip.sina.com
hqylfy 2003-09-18
  • 打赏
  • 举报
回复
我也用过ADO做线程
也是类似的错误
Atomictry 2003-09-18
  • 打赏
  • 举报
回复
yesry 2003-09-16
  • 打赏
  • 举报
回复
void __fastcall TServerFrm::UpdateField(String updatefield,String updatevalue,String sourcefield,String sourcevalue)
//说明:updatefield为需要更新的字段,updatevalue为需要更新的字段值
// sourcefield为已知字段,updatevalue为已知字段值,如上面的RemoteHostIP
{
String Updatesql="update LinkRecord set "+updatefield;

Updatesql+= "='"+updatevalue+"' where "+sourcefield;

Updatesql+= "='"+sourcevalue+"'";

TADOQuery *q=new TADOQuery(ADOConnection1);
q->Connection=ADOConnection1;//各个线程可以间接公用ADOConnection1,但是ADOQuery不能共享访问
q->Execute(Updatesql);
delete q;
}


invalid 2003-09-16
  • 打赏
  • 举报
回复
那就看是不是设置或者其它什么问题了。
Angelic 2003-09-16
  • 打赏
  • 举报
回复
楼上,ADOQuery没有Execute()方法。谢你一次。

我在线程里其实用了同样的方式做过了也不行:
void __fastcall Server::Newquery()
{
TADOQuery *Newado;
try
{
Newado=new TADOQuery(NULL);
Newado->Connection=ServerFrm->ADOConnection1;
Newado->Close();
Newado->SQL->Clear();
Newado->SQL->Add("select * from customerlinkrecord");
Newado->Open();
}
__finally
{
delete Newado;
}
}
Atomictry 2003-09-16
  • 打赏
  • 举报
回复
啊?怎么这么命苦?
1.ADOConnection1一些设置,其他默认:
Connected>>>true;ConnectonString>>>是通过数据源连接的;

2.ADOQuery通过new生成,如下:
void __fastcall Server::Newquery()
{
TADOQuery *Newado;
try
{
Newado=new TADOQuery(NULL);
Newado->Connection=ServerFrm->ADOConnection1;
Newado->Close();
Newado->SQL->Clear();
Newado->SQL->Add("select * from linkrecord");
Newado->Open();
}
__finally
{
delete Newado;
}
}

然后就是调用,没了。
我也完了,这么个问题都搞不定。
kinglh 2003-09-15
  • 打赏
  • 举报
回复
继续顶
Atomictry 2003-09-15
  • 打赏
  • 举报
回复
to pbMaster(pb高手) :
如果你只是用来插入或者更新操作,用我上面的UpdateField()方法就可以了。


to invalid(空心菜):
菜老师好象不行啊,还是“[Microsoft][ODBC SQL Server Driver]连接占线导致另
一个hstmt.”错误。
我设置代码保护都没有用,new 应该也没有效果。ADO不知道究竟什么问题。



Atomictry 2003-09-15
  • 打赏
  • 举报
回复
to invalid(空心菜):
我仍然叫你菜老师吧,我先试一下你的办法。谢你先。

谢谢朋友们。
Atomictry 2003-09-15
  • 打赏
  • 举报
回复
比如在连接的时候我需要将此次连接记录到数据库的一张表中。
void __fastcall Server::ClientExecute()
{
Connected(); //客户端连接;
try{
Disposal();
}
catch(...){
DisConnected();
}
}

Connected()函数如下:
void __fastcall Server::Connected()
{
RemoteHostIP=ClientSocket->RemoteAddress;

RemoteHostPort=ClientSocket->RemotePort;

ServerFrm->UpdateField("State","连接","RemoteIP",RemoteHostIP);//已
经把将要连接上的远程客户机的IP记录在数据库的一张表中,即RemoteHostIP在数据
库已经存在了记录。

ServerFrm->UpdateField("Port",RemoteHostPort,"SourceIP",
RemoteHostIP); //同上

ServerFrm->UpdateDBGrid("LinkRecord"); //刷新DBGrid控件
}

UpdateField()函数如下:
void __fastcall TServerFrm::UpdateField(String updatefield,String updatevalue,String sourcefield,String sourcevalue)
//说明:updatefield为需要更新的字段,updatevalue为需要更新的字段值
// sourcefield为已知字段,updatevalue为已知字段值,如上面的RemoteHostIP
{
String Updatesql="update LinkRecord set "+updatefield;

Updatesql+= "='"+updatevalue+"' where "+sourcefield;

Updatesql+= "='"+sourcevalue+"'";

ADOConnection1->Execute(Updatesql);
}

UpdateGrid()函数如下:
void __fastcall TServerFrm::UpdateDBGrid(String SQLName)//查询一次记录集
{
ADOQuery1->Close();

ADOQuery1->SQL->Clear();

ADOQuery1->SQL->Add("select * from "+SQLName);

ADOQuery1->Open();
}

1. 我是在一台机子上开了六个客户端模拟几乎同时连接到服务端的情况,是不是因为六个
RemoteHostIP是数据库里的同一个记录引起的“对象已打开操作”的错误?

2. 跟踪到线程,发现执行到ServerFrm->UpdateDBGrid("LinkRecord"); 时
发生“[Microsoft][ODBC SQL Server Driver]连接占线导致另一个hstmt.”错误

3. 有时候也会产生“在异步运行时,操作不能被执行”的错误,不过较少发生。

4. 注释掉UpdateDBGrid(),程序不再出错,但界面上DBGrid不能够进行动态刷新显示。

我用Synchronize进行同步和用TCriticalSection设置代码保护区都试过了,都是出现相同错误:
“[Microsoft][ODBC SQL Server Driver]连接占线导致另一个hstmt.”


to AKing:在线程查询语句会出错吗?该怎么用才可以用select查询语句?

请朋友们帮帮忙啊!
invalid 2003-09-15
  • 打赏
  • 举报
回复
我写过可以的,我采用的数据库是Access。有多种线程,多线程实例。
pbMaster 2003-09-15
  • 打赏
  • 举报
回复
Atomictry (天影) :
我们可能是在做几乎同样的开发任务,我也卡到这里了,可以交流一下!

MSN catmiwang@hotmail.com
qq 154863618
pbMaster 2003-09-15
  • 打赏
  • 举报
回复
invalid(空心菜) :
这是不行的!不信你试验一下!
invalid 2003-09-15
  • 打赏
  • 举报
回复
每个线程New一个TadoQuery组件,连接到公共的AdoConnection组件就可以了。
加载更多回复(4)

1,178

社区成员

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

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