基于 ATL/OLE DB 的动态数据库类






4.96/5 (18投票s)
2002年4月24日
2分钟阅读

128837

4435
一个使用 ATL/OLE DB 技术动态操作数据库数据的类
引言
想象一下能够从客户端动态访问数据库的优势。 您可以从客户端动态查询数据库,或者动态填充下拉选择列表,或者动态更新表的某些字段,这只是几种可能性。 实际上,借助 CSQLQuery
对象,您可以做到这一点。 本文介绍了基于 ATL/OLE DB
库的动态类 CSQLQuery
,并提供了一些示例。
提交 SQL 语句并检索数据
要提交 SQL 语句,您只需实例化一个 CSQLQuery
对象,然后调用 ExecuteSQL
成员函数,并将 SQL 字符串作为参数传递。
CSQLQuery query(GetSession()); query.ExecuteSQL("SELECT MAX(UnitPrice) FROM Products");
检索数据就像 1,2,3 一样简单。 为此,您只需定义变量,然后使用重载运算符(例如 >>
)获取数据。
double dblUnitPrice = 0; query >> dblUnitPrice;
注意:在这种情况下,您必须注意数据映射。 例如,像 int
这样的 SQL Server 数据应该映射到 C++ long
类型。
要将任何数据检索为字符串并避免映射,您可以使用运算符 >
,如下所示
CString str; query > str.
在这种情况下,您不必担心数据映射。 所有类型的数据都将自动映射到 CString
对象。
您还可以使用重载运算符,例如 <<
来传递参数
double dblMaxPrice = 2.8; CSQLQuery query(GetSession()); query << "SELECT ProductName,UnitPrice FROM Products WHERE UnitPrice > " << dblMaxPrice; query.ExecuteSQL();
带有参数的存储过程的执行可能如下所示
double dblPar1 = 2.8, dblPar2 = 1.8; CSQLQuery query(GetSession()); query << "EXECUTE sp_MyProcedure " << dblPar1 << " , " << dblPar2; query.ExecuteSQL();
SQL 更新语句也不会很复杂
CSQLQuery query(GetSession()); query << "UPDATE Orders SET ShipName = 'MyName' WHERE EmployeeID = 5"; query.ExecuteSQL();
使用对象的示例
列表框填充的示例
在此示例中,函数 PoulateListBox
的填充取决于参数 dblMaxPrice 的值。 列表框将填充 UnitPrice 大于 dblMaxPrice 的数据。 您可以将该想法扩展到任何条件来检索数据。
void PoulateListBox(CListBox& box,double dblMaxPrice) { box.ResetContent(); CSQLQuery query(GetSession()); query << "SELECT ProductID,ProductName FROM Products WHERE UnitPrice > " << dblMaxPrice; if(!query.ExecuteSQL()) return; while(!query.eof()) { LONG lProductID = 0; CString strProductName; query >> lProductID >> strProductName; int idx = box.AddString(strProductName); box.SetItemData(idx,lProductID); } }
CListCtrl 填充的示例
此示例显示了如何使用列和数据填充 CListCtrl。
void CQueryView::ShowQuery(const CString strTableName) { // Clear List control m_listCtrl.DeleteAllItems(); while(m_listCtrl.DeleteColumn(0)) {} CSQLQuery query(GetSession()); query << " SELECT TOP 100 * FROM " << strTableName; if(!query.ExecuteSQL()) return; // Show columns int cols = query.GetColumnsCount(); for( int nCol = 0; nCol < cols; nCol++) { CString strColName = query.GetColumnName(nCol); m_listCtrl.InsertColumn(nCol,strColName,LVCFMT_LEFT,80); } // Show data int nItem = 0; while(!query.eof()) { CString str; query > str; m_listCtrl.InsertItem(nItem,str); for( int nSubItem = 1; nSubItem < cols; nSubItem++) { CString str; query > str; m_listCtrl.SetItemText(nItem,nSubItem,str); } nItem++; } }
是不是很简单?
关于 GetSession()
CSQLQuery
对象正在使用指向 CSession
class
的指针。 CSession
对象表示在 ATL
库中定义的单个数据库访问会话。 要为 CDataSource
创建新的 CSession
,只需实例化一个对象
CDataSource m_datasource; CSession m_session;然后使用以下函数创建一个:
bool Connect(ATL::CDataSource* pDataSource,ATL::CSession* pSession) { ASSERT(pDataSource); CComBSTR bstrServer(m_strServerName); CComBSTR bstrUser(m_strLoginName); CComBSTR bstrPassword(m_strPassword); CComBSTR bstrDatabase(m_strDatabaseName); if (pSession && pSession->m_spOpenRowset != NULL) pSession->m_spOpenRowset.Release(); CDBPropSet dbinit(DBPROPSET_DBINIT); dbinit.AddProperty(DBPROP_AUTH_PASSWORD, bstrPassword); dbinit.AddProperty(DBPROP_AUTH_PERSIST_SENSITIVE_AUTHINFO, false); dbinit.AddProperty(DBPROP_AUTH_USERID, bstrUser); dbinit.AddProperty(DBPROP_INIT_CATALOG, bstrDatabase); dbinit.AddProperty(DBPROP_INIT_DATASOURCE, bstrServer); dbinit.AddProperty(DBPROP_INIT_LCID, (long)1049); dbinit.AddProperty(DBPROP_INIT_PROMPT, (short)4); if(FAILED(pDataSource->Open(_T("SQLOLEDB.1"), &dbinit))) { pDataSource->Close(); return false; } else { if (pSession && pSession->Open(*pDataSource) != S_OK) { return false; } } return true; }所以,
GetSession()
看起来像这样:CSession* GetSession()
{
return &m_session;
}
关于演示的说明
本文的演示项目已在 SQL Server 7.0/8.0 和 Northwind 数据库上进行了测试。 我认为,要连接到另一种类型的数据库(例如 Oracle),更改函数Connect
就足够了。