环境:vs 2003,MFC +ODBC数据源
我希望在程序中可以实现部分高级查询(参数化查询),然而又希望程序具有较好的容错性。一些
结果描述如下:
class CPointSet:public CRecordSet
{……
CStringA m_QueryCondition; //用于参数化记录集
……
};
CPointset m_PointSet;
……
m_PointSet.m_strFilter=m_QueryCondition; //在Requery()前设定参数,实现参数化查询
m_PointSet.Requery(); 问题:如何检验m_strFilter 语句的合法性??
如果 该语句不合法,那么,程序会有异常,因为CRecordSet->IsDeleted()为真。
为了更好的说明问题,举例如下:
m_strFilter = "1=1"; //合法语句,相当于没有参数化查询
m_strFilter = "0" ; //不合法语句,程序会抛出异常。我是想如果m_strFilter语句不合法,我就把它替换成 m_strFilter = "1=1";即合法的语句。
不知道这该如何实现呢?
我希望在程序中可以实现部分高级查询(参数化查询),然而又希望程序具有较好的容错性。一些
结果描述如下:
class CPointSet:public CRecordSet
{……
CStringA m_QueryCondition; //用于参数化记录集
……
};
CPointset m_PointSet;
……
m_PointSet.m_strFilter=m_QueryCondition; //在Requery()前设定参数,实现参数化查询
m_PointSet.Requery(); 问题:如何检验m_strFilter 语句的合法性??
如果 该语句不合法,那么,程序会有异常,因为CRecordSet->IsDeleted()为真。
为了更好的说明问题,举例如下:
m_strFilter = "1=1"; //合法语句,相当于没有参数化查询
m_strFilter = "0" ; //不合法语句,程序会抛出异常。我是想如果m_strFilter语句不合法,我就把它替换成 m_strFilter = "1=1";即合法的语句。
不知道这该如何实现呢?
或者:有办法阻止程序抛出异常吗?(似乎不可能,CRecordSet的实现不是我们能决定的)
或者按你说的,
m_strFilter = "1=1";m_PointSet.Requery();
我也捕获了异常,但是CRecordSet内建的异常我们无法阻止: //***catch语句是为了防止当高级查询时查询条件输入错误
try
{
m_pPointSet->Requery(); //重建记录集
m_pArcSet->Requery(); //重建记录集
}
catch(...)
{
assert(m_pPointSet && m_pArcSet);
AfxMessageBox(_T("哦哦哦哦哦……很抱歉,查询条件错误。你必须重新启动应用程序。"));
return;
}
m_strFilter = "0" ; //不合法语句,程序会抛出异常。
当m_strFilter非法时,提交查询,我的捕获异常的程序弹出一个窗口“("哦哦哦哦哦……很抱歉,查询条件错误。你必须重新启动应用程序。"));”。捕获异常的程序见楼上的楼上所提供。
其它的并没有别的提示。
然而,当企图再次查询数据库时,断言失败:Debug Assertion Failed!
Program: g:\code\...\Debug\SP.exe
File: f:\vs70builds\3077\vc\MFCATL\ship\atlmfc\include\afxdb.inl
Line:52
{
ASSERT_VALID(this);
ASSERT(IsOpen()); //******************在此失败
ASSERT(!(m_dwOptions & useMultiRowFetch));即使我捕获了异常,也没有用。 try
{
m_pPointSet->Requery(); //重建记录集
m_pArcSet->Requery(); //重建记录集
}
catch(...)
{
assert(m_pPointSet && m_pArcSet);
AfxMessageBox(_T("哦哦哦哦哦……很抱歉,查询条件错误。你必须重新启动应用程序。"));
m_pPointSet->m_strFilter="1=1";
m_pArcSet->m_strFilter="1=1";
return;
}
先把错误的情况标注在代码中 try
{
m_pPointSet->Requery(); //重建记录集
m_pArcSet->Requery(); //重建记录集
}
catch(...)
{
assert(m_pPointSet && m_pArcSet);
AfxMessageBox(_T("哦哦哦哦哦……很抱歉,查询条件错误。你必须重新启动应用程序。"));
m_pPointSet->m_strFilter="1=1";
m_pArcSet->m_strFilter="1=1";
//UpdateData(false);
if(! m_pPointSet->IsOpen())
m_pPointSet->Open(); //断言失败。
//CRecordSet::PrepareAndExecute() 抛出异常,原因是:
//pszSQL "SELECT "pointID","x","y","nearArcNum","pPointIDName","trafficLight",
"noNbrLight","trafficLightState" FROM "dbo"."Point" WHERE 0"
//注意,WHERE 0 语句,m_strFilter并没有改变,虽然我前面已经改变了值
//m_pPointSet->m_strFilter="1=1";
if(! m_pArcSet->IsOpen())
m_pArcSet->Open();
m_pPointSet->Requery(); //重建记录集
m_pArcSet->Requery(); //重建记录集
UpdateData(false);
return;
}
由于上面的pszSQL出现了我非预见的情况,因此我特地查了一下自己定义的
CPointSet (:public CRecordSet),发现我的GetDefaultSQL()语句居然这样子写:
CString CPointSet::GetDefaultSQL()
{
m_strFilter=m_Query ;
return _T("[dbo].[Point]");
}
而我上面的捕获异常程序只是改动了m_strFilter的值,并没有改动m_Query的值。
因此,m_strFilter的值又重新被赋值为错误的信息了。后来把 m_strFilter=m_Query ;语句删掉,就可以了。
(或者不删掉该语句,而是在捕获异常时加上以下两句:
m_pPointSet->m_Query="1=1";
m_pArcSet->m_Query="1=1";
)
即可。谢谢楼上各位兄弟给我提供的意见。