您的位置:首页 > 其它

能否不重载CRecordSet类,用MFC ODBC调用带返回值和参数的存储过程

2009-05-18 02:27 495 查看

能否不重载CRecordSet类,用MFC ODBC调用带返回值和参数的存储过程

楼主casale(无三)2005-06-28 18:40:16 在 VC/MFC / 数据库 提问

重载CRecordSet的方法本人已经知道,但我要调用的类似存储过程有好多个,不想一个个重载,请高手指教!还有,只能用MFC ODBC,其他方法就不要了。
问题点数:50、回复次数:6Top

1 楼ok1234567(ok1234567)回复于 2005-06-28 19:40:23 得分 50

如下代码供你参考:
CREATE PROCEDURE [cp_man_work_del]
@wiid int

AS

SET NOCOUNT ON
/*
[man_work] (
[wiid] [int] IDENTITY (1, 1) NOT NULL ,
[wcmode] [char] (1) NOT NULL
*/
DECLARE @cmode char(1)
SELECT @cmode=wcmode FROM man_work WHERE wiid=@wiid

IF @cmode IS NULL RETURN -2
IF @cmode = 'C' RETURN -3

DELETE man_work WHERE wiid=@wiid
IF @@ERROR <> 0 RETURN -9

RETURN @wiid
//存储过程结束
C++ 程序要点
#include <afxdb.h>

BOOL CWorkPage::DoDelete()
{
UpdateData();
//------------------------------------
SQLRETURN retcode;
SQLHENV m_henv;
SQLHDBC m_hdbc;
retcode = SQLAllocHandle(SQL_HANDLE_ENV,SQL_NULL_HANDLE,&m_henv);
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
{
AfxMessageBox("数据库环境句柄分配错误。");
return FALSE;
}
retcode = SQLSetEnvAttr(m_henv, SQL_ATTR_ODBC_VERSION, (void*)SQL_OV_ODBC3, 0);
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
{
AfxMessageBox("数据库环境句柄设置错误。");
return FALSE;
}

retcode =SQLAllocHandle(SQL_HANDLE_DBC,m_henv,&m_hdbc);
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
{
AfxMessageBox("数据库连接句柄分配错误。");
return FALSE;
}
//Set login timeout to 20 seconds.
SQLSetConnectAttr(m_hdbc, SQL_LOGIN_TIMEOUT, (void*)20, 0);
// Connect to data source
retcode = SQLConnect(m_hdbc,(SQLCHAR*) m_szDSN, SQL_NTS,
(SQLCHAR*) m_szUID, SQL_NTS,
(SQLCHAR*) m_szPWD, SQL_NTS);
if (retcode != SQL_SUCCESS && retcode != SQL_SUCCESS_WITH_INFO)
{
AfxMessageBox("数据库连接错误。");
return FALSE;
}

SQLHSTMT hstmt = SQL_NULL_HSTMT;
if(SQLAllocHandle(SQL_HANDLE_STMT, m_hdbc, &hstmt)!=SQL_SUCCESS)
{
AfxMessageBox("数据库操作句柄分配错误。");
return FALSE;
}

SQLHSTMT hstmt = SQL_NULL_HSTMT;
SQLINTEGER siRetCode,cbRet;
siRetCode =0;
if(SQLAllocHandle(SQL_HANDLE_STMT, m_hdbc, &hstmt)!=SQL_SUCCESS)
{
MessageBox("数据库操作句柄分配错误,操作失败。");
return FALSE;
}
m_pCatvView->m_pMainWindow->m_pApp->SetDBState();

char szSql[96];
sprintf(szSql,
"{?=CALL catv.dbo.cp_man_work_del(%d)}",
m_iCurID);
retcode =SQLBindParameter(hstmt,
1,
SQL_PARAM_OUTPUT,
SQL_C_SLONG,
SQL_INTEGER,
0,
0,
&siRetCode,
0,
&cbRet);
if (!(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO))
{
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
MessageBox("数据库参数绑定错误。","提示");
return FALSE;
}
retcode =SQLExecDirect(hstmt,(unsigned char *)szSql,SQL_NTS);
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
m_pCatvView->m_pMainWindow->m_pApp->SetDBState(TRUE);
if (!(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) || siRetCode == -9)
{
MessageBox("数据库内部错误,操作未完成。");
return FALSE;
}

if(siRetCode < 0)
{
switch(siRetCode)
{
case -2:
MessageBox("任务记录不存在,可能刚被删除。");
break;
case -3:
MessageBox("任务已经完成,不能删除。");
break;
default:
MessageBox("未知的数据库内部错误,操作未完成。");
}
return FALSE;
}

return TRUE;
}

以上为要点,是从我的程序里拷贝的
变量不完整,看变量名应该就明白了
另外,在程序中,
m_henv只建一个
m_hdbc 有限个(初始化为连接池),通过一定的同步机制,从连接池中获取,这样可以提高程序的效率

Top

2 楼ok1234567(ok1234567)回复于 2005-06-28 19:52:54 得分 0

如下为一个没有改动的delete方法,
上面拷贝的代码有重复,对照参考,应该可以完成的设计目标:)

BOOL CWorkPage::DoDelete()
{
UpdateData();
//------------------------------------
if(!m_pCatvView->m_pMainWindow->m_pApp->GetDBState())//获得连接句炳,全部程序共用一个
{
MessageBox("数据库忙,等会再试。","提示");
return FALSE;
}
SQLRETURN retcode;
SQLHSTMT hstmt = SQL_NULL_HSTMT;
SQLINTEGER siRetCode,cbRet;
siRetCode =0;
if(SQLAllocHandle(SQL_HANDLE_STMT, m_pCatvView->m_pMainWindow->m_pApp->m_hdbc, &hstmt)!=SQL_SUCCESS)
{
MessageBox("数据库操作句柄分配错误,操作失败。");
return FALSE;
}
m_pCatvView->m_pMainWindow->m_pApp->SetDBState();//设置连接句柄被使用标志

char szSql[96];
sprintf(szSql,
"{?=CALL catv.dbo.cp_man_work_del(%d)}",
m_iCurID);
retcode =SQLBindParameter(hstmt,
1,
SQL_PARAM_OUTPUT,
SQL_C_SLONG,
SQL_INTEGER,
0,
0,
&siRetCode,
0,
&cbRet);
if (!(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO))
{
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
m_pCatvView->m_pMainWindow->m_pApp->SetDBState(TRUE);
MessageBox("数据库参数绑定错误。","提示");
return FALSE;
}
retcode =SQLExecDirect(hstmt,(unsigned char *)szSql,SQL_NTS);
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
m_pCatvView->m_pMainWindow->m_pApp->SetDBState(TRUE);//清除使用标志
if (!(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO) || siRetCode == -9)
{
MessageBox("数据库内部错误,操作未完成。");
return FALSE;
}

if(siRetCode < 0)
{
switch(siRetCode)
{
case -2:
MessageBox("任务记录不存在,可能刚被删除。");
break;
case -3:
MessageBox("任务已经完成,不能删除。");
break;
default:
MessageBox("未知的数据库内部错误,操作未完成。");
}
return FALSE;
}

m_lst.DeleteItem((int)m_posCur-1);

DoClear();
return TRUE;
}Top

3 楼ok1234567(ok1234567)回复于 2005-06-28 20:04:10 得分 0

参数的返回:

CREATE PROCEDURE [cp_get_topic_search_page]
@itotal int OUTPUT,
@str varchar(8000) OUTPUT,
@iindex int
.....
SELECT @itotal=COUNT(1) FROM ....
.....
RETURN 0

......
strcpy(pDB->szSql,"{?=CALL ");
strcat(pDB->szSql,szDBName);
strcat(pDB->szSql,".dbo.cp_get_forum_topic_search_page(?,?,20,");
.......

// -- begin to bind 3 parameters ----
retcode =SQLBindParameter(hstmt,
1,
SQL_PARAM_OUTPUT,
SQL_C_SLONG,
SQL_INTEGER,
0,
0,
&(pDB->siRetCode),
0,
&(pDB->cb[0]));
if (!(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO))
{
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
pDB->bIdle=TRUE;
MessGen(pCtxt,pDataWeb->m_szName,CMessPub::BusyRetry,2);
return ;
}
retcode =SQLBindParameter(hstmt,
2,
SQL_PARAM_OUTPUT,
SQL_C_SLONG,
SQL_INTEGER,
0,
0,
&(pDB->siTotal),
0,
&(pDB->cb[1]));
if (!(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO))
{
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
pDB->bIdle=TRUE;
MessGen(pCtxt,pDataWeb->m_szName,CMessPub::BusyRetry,2);
return ;
}
retcode =SQLBindParameter(hstmt,
3,
SQL_PARAM_OUTPUT,
SQL_C_CHAR,
SQL_CHAR,
8000,
0,
pDB->scStr,
8002,
&(pDB->cb[2]));
if (!(retcode == SQL_SUCCESS || retcode == SQL_SUCCESS_WITH_INFO))
{
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
pDB->bIdle=TRUE;
MessGen(pCtxt,pDataWeb->m_szName,CMessPub::BusyRetry,2);
return ;
}
//-- bind parameters end ---

SQLExecDirect后,这些参数就可以用了Top

4 楼casale(无三)回复于 2005-06-28 20:18:52 得分 0

一二三楼的老兄,你的代码用的是ODBC API吧!这个我也看过啊,还是很不方便的啊,比重载CRecordSet好不到哪啊!我就是不想太麻烦啊,就没办法直接用MFC ODBC吗Top

5 楼ok1234567(ok1234567)回复于 2005-06-28 21:55:39 得分 0

MFC 封装的database类运行效率是很低的
我用过一段时间,忍受不了他的效率,所以后来都用ODBC API了
我对MFC 封装的database类只用了一年多
没有找到其直接回传参数的接口

ODBC API看起来复杂,其实不难
可以自己封装几个类,开发效率不是问题

Top

6 楼pieapple()回复于 2005-07-03 02:11:57 得分 0

请问楼主能不能把那个CRecordSet重载的方法贴一下啊? 我最近也遇到类似的问题, 谢谢啊!Top
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐