65.9K
CodeProject 正在变化。 阅读更多。
Home

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

2002年4月24日

2分钟阅读

viewsIcon

128837

downloadIcon

4435

一个使用 ATL/OLE DB 技术动态操作数据库数据的类

Sample Image - CSQLQuery.jpg

引言

想象一下能够从客户端动态访问数据库的优势。 您可以从客户端动态查询数据库,或者动态填充下拉选择列表,或者动态更新表的某些字段,这只是几种可能性。 实际上,借助 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 就足够了。
© . All rights reserved.