ADO连数据操作中,出现ADO异常的情况下如何关闭记录集(m_recordset)了?

cql0007 2006-05-18 12:16:28
使用ADO的连接方式.

ADO类做为单例的,在初始化就已经建立好连接(m_connection)和记录集(m_recordset)了.

在不同的数据库操作的方法中直接使用连接和记录集.

例如在插入记录时:
//打开记录集:
try{
hr = m_recordset->Open(query, source, adOpenDynamic,
adLockOptimistic, adCmdText);
}

//执行插入
try{
m_recordset->AddNew();
...........

m_recordset->Update();
fields->Release();
field->Release();
m_recordset->Close();


return true;
}
catch(_com_error &e2){
CString str=(char*)e2.ErrorMessage();
str += e2.Description();
::MessageBox(NULL,str+"\r\n插入数据出错。","提示",
MB_OK | MB_ICONWARNING);

m_recordset->Close();///?????这里有问题了?
return false;
}

问题出在在catch{}语句,如果插入数据不成功,跳到catch块后,这个地方不能执行:m_recordset->Close(),一执行就导致程序死掉了.
但如果这里不关闭记录集就直接退出的话,程序是可以接着运行,但这个m_recordset没有Close掉,下次进到这个方法中时或者下次别的方法中要用到m_recordset时,一打开记录集就出错,因为这个记录集是没有关闭的
//打开记录集:
try{
hr = m_recordset->Open(query, source, adOpenDynamic,
adLockOptimistic, adCmdText);
}
//这里出错.

这样一来,就导致我的程序一出现ADO错误就会死掉.因为如何处理这个问题了?
...全文
835 29 打赏 收藏 转发到动态 举报
写回复
用AI写文章
29 条回复
切换为时间正序
请发表友善的回复…
发表回复
cql0007 2006-06-06
  • 打赏
  • 举报
回复
暂时发现,用 yhmhappy2006(Nathan) 的方法


在catch中写上:
m_pSet->CancelUpdate();

可以解决我的问题了。

而且还补充一点发现:如果是在Execute方法中抛出的异常
m_connection->Execute
用CancelUpdate()不行了,这个地方用个Cancel()就OK了,目前现在我应用中的这种出错问题就是用这两个方法都解决了,其它的老兄说的很多的各种各样的方法都没有解决问题。

不知还有哪位老兄有什么高见没?


jazy 2006-06-06
  • 打赏
  • 举报
回复
lz一味考虑catch之后的问题,虽然是需要的,不过建议你还是多找找异常发生的原因,尽量不让异常发生的好,真正健康的程序,不应该处处是try的。就目前lz的描述,我觉得可以修正的错误肯定还有,建议你把
catch(_com_error &e2){
CString str=(char*)e2.ErrorMessage();
str += e2.Description();
::MessageBox(NULL,str+"\r\n插入数据出错。","提示",
MB_OK | MB_ICONWARNING);
的提示信息多研究一下,解决问题而不是掩盖问题的好
Aizz 2006-06-06
  • 打赏
  • 举报
回复
没看懂楼主需要的是什么。

实际上,对记录集的操作取消就三个:Cancel / CancelUpdate / CancelBatch ,再加上事务,怎么处理我想楼主已经清楚了,我就不废话了。
通常情况下,对记录的修改,我建议不要依赖异常机制来处理(或者说依赖数据库来鉴错),而应该采取自己对修改的数据做校验的方式,毕竟本地对数据做一个比较比送到数据库再返回错误快多了。

另外,有种方法楼主可以尝试一下,在 ADO 之上封装异常机制形成一个类/类库,细心一点儿,也算是一种锻炼吧。
cql0007 2006-06-06
  • 打赏
  • 举报
回复
分不够散了,没办法了,只能加到100了
cql0007 2006-06-06
  • 打赏
  • 举报
回复
多谢各位了,我开始就是不知道使用Cancel / CancelUpdate / CancelBatch 这三个方法。

现在问题已经解决了,不过我也还是不太明白Cancel / CancelUpdate / CancelBatch这三者之间的区别。

我也知道最好是不让问题发生,不让ADO异常出现,在每次操作数据库之前都检查一下数据的合法性,不过这个catch总得有一个啊,总得处理处理这种万一发生的情况啊。

再次谢谢各位了。
Aizz 2006-06-05
  • 打赏
  • 举报
回复
如果需要操作记录集,比如:
try
{
pRs->AddNew();
// ...
// 建议在 Update() 处进行额外的异常捕捉,以便定位错误的发生位置或日志记录
// 这样做可以使 Update() 发生的错误区域化,不会导致整个处理失败
try
{
pRs->Update();
}
catch ()
{
// 这里可以记录错误信息...
pRs->CancelUpdate();
}
}
catch ()
{
}

其它的比如事务等的异常处理都可以这样实现。
忠向 2006-06-05
  • 打赏
  • 举报
回复
aizz的点子不错,言简意赅
Mark!
塘外人 2006-06-04
  • 打赏
  • 举报
回复
晕,这个问题很容易解决的,你只要把关闭连接的语句改成这样的条件语句就行了:
if(m_recordset->State)
m_recordset->Close();

----------------
问题就是这里,在m_recordset->Close();出错啊
tangbo6 2006-06-04
  • 打赏
  • 举报
回复
注意了上面的语句是if(m_recordset->State)不要写成if(m_recordset->State())了,不然会出错的
tangbo6 2006-06-04
  • 打赏
  • 举报
回复
晕,这个问题很容易解决的,你只要把关闭连接的语句改成这样的条件语句就行了:
if(m_recordset->State)
m_recordset->Close();
塘外人 2006-06-04
  • 打赏
  • 举报
回复
发现一个解决方法:
在catch中写上:
m_pSet->CancelUpdate();
塘外人 2006-06-04
  • 打赏
  • 举报
回复
我昨天刚学vc数据库,一开始 就碰到了楼主同样的错误
也是,我在添加记录的时候故意添加一条主键和另一条一样的记录
结果发生异常:
MessageBox(e.ErrorMessage());//跳出对话框:Dispatch error #3119
然后这个打开的_RecordsetPtr就不能用了,如果在其他地方用,
也会产生异常:Dispatch error #3119

头痛,不知如何解决?

楼主知道的话,请一定告诉我

谢谢
cql0007 2006-06-03
  • 打赏
  • 举报
回复
非常感谢Aizz(Nova)

用你的方法,发现一个很奇怪的问题。

就是有的地方用它可以行的能,有的地方行不通。

例如,如果我是在读数据时,读一个不存在的列名时发生的ADO异常,用上面的方法处理正常。

但如果是在插入数据有主键重复时这种ADO异常,那用上面的方法还是一样,在执行pRs->Close();
这句时会程序死掉。

为什么会这样了?

是不是大家很多人都是每次进一个查询就构造一个recordSet了,把它做局部变量,一出方法就不用了,下次进来查询,更新数据时再重新构造这个recordSet了?

不然如果始终用一个recordSet来操作,为什么会搞的象我现在这样麻烦了,程序根本没办法正常用了,动不动就死掉了
Aizz 2006-06-03
  • 打赏
  • 举报
回复
一定能行的解决方案:

_RecordsetPtr pRs(_T("ADODB.Recordset"));
try
{
// open recordset
pRs->Open(...)
// do anything you want
// ...
// success, close recordset
pRs->Close();
}
catch (...) // exception
{
// check recordset state
if (pRs->State == adStateOpen)
{
pRs->Close();
}
}
ConnectionPtr 和 RecordsetPtr 的处理方法一样。

PS:建议,在 try-catch 中最好不要使用 return ,尽量使用 throw 抛出异常,让 catch 执行完异常处理后自动退出
cql0007 2006-05-31
  • 打赏
  • 举报
回复
UPUPUP


UPUPUP
cql0007 2006-05-30
  • 打赏
  • 举报
回复
}catch (_com_error &e){
CString str=(char*)e.ErrorMessage();
str += "\r\n";
str += e.Description();
::MessageBox(NULL,str+"\r\n读数据发生异常。","提示",
MB_OK | MB_ICONWARNING);

m_recordset->Release();
return "";
}
不行,程序在catch块中就死掉了
fjfzb 2006-05-30
  • 打赏
  • 举报
回复
你在抛出异常后在catch中加入m_recordset->Resease()就行了,
cql0007 2006-05-26
  • 打赏
  • 举报
回复
UP
cql0007 2006-05-22
  • 打赏
  • 举报
回复
多谢楼上老兄了

我在关闭之前是判断了一下,现在也放在了try块中

}catch(_com_error &e2){
CString str=(char*)e2.ErrorMessage();
str += e2.Description();
::MessageBox(NULL,str+"\r\n插入数据出错。\r\nCHMSADOOperate::InsertRow","提示",
MB_OK | MB_ICONWARNING);



bb = m_recordset->GetState();
try{
if (adStateClosed != m_recordset->GetState())
{
m_recordset->Close();
TRACE("异常关闭正常");
}
}catch(_com_error &e){

return "";
}
}

但问题还是原来的个问题啊,在try中m_recordset->Close()还是出异常,虽然它被catch住了不会导致程序死掉,但就这样退出去的话,这个m_recordset还是没有被关闭掉啊,下次再插入数据再要用到这个m_recordset时,还是会出错程序用不了啊.


是不是每一次的ADO操作都要建立一次m_recordset,用完就销毁它,下次再有数据操作再建立一个了?我总觉得这样有点浪费资源的

CSDN论坛浏览器:http://CoolSlob.ys168.com/
ringphone 2006-05-22
  • 打赏
  • 举报
回复
我是专门写了一个Close的函数,在这个函数里要判断这个结果集必须有效且在打开状态才能关闭,同时这些操作代码都是放在try,catch块中的,这样在catch中调用Close就不会因再次异常而死掉。
加载更多回复(9)

4,012

社区成员

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

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