使用数据库特性简化数据访问

本主题演示如何使用数据库特性来简化数据库操作。

从数据库访问信息的基本方法是为数据库中的特定表创建命令(或表)类和用户记录类。 数据库特性简化了以前必须执行的某些模板声明。

为演示数据库特性的使用,以下部分显示了两个等效表和用户记录类声明:第一个使用特性,第二个使用 OLE DB 模板。 此类声明代码通常放置在针对表或命令对象命名的头文件中,例如,Authors.h。

通过比较这两个文件,可以看到使用特性更为简单。 区别在于:

  • 使用特性时,只需声明一个类:CAuthors,而使用模板必须声明两个类:CAuthorsNoAttrAccessorCAuthorsNoAttr

  • 特性化版本中的 db_source 调用等效于模板声明中的 OpenDataSource() 调用。

  • 特性化版本中的 db_table 调用等效于以下模板声明:

    class CAuthorsNoAttr : public CTable<CAccessor<CAuthorsNoAttrAccessor>>
    
  • 特性化版本中的 db_column 调用等效于模板声明中的列映射(请参阅 BEGIN_COLUMN_MAP ... END_COLUMN_MAP)。

这些特性会注入用户记录类声明。 用户记录类等于模板声明中的 CAuthorsNoAttrAccessor。 如果表类是 CAuthors,则注入的用户记录类命名为 CAuthorsAccessor,并且只能在注入的代码中查看其声明。 有关详细信息,请参阅用户记录中的“注入特性的用户记录类”。

在特性化代码和模板化代码中,必须使用 CDBPropSet::AddProperty 设置行集属性。

有关本主题中讨论的特性的信息,请参阅 OLE DB 使用者特性

注意

编译下方示例需要以下 include 语句:

#include <atlbase.h>
#include <atlplus.h>
#include <atldbcli.h>

使用特性的表和访问器声明

以下代码调用表类上的 db_sourcedb_tabledb_source 指定要使用的数据源和连接。 db_table 注入适当的模板代码以声明表类。 db_column 指定列映射并注入访问器声明。 可以在支持 ATL 的任何项目中使用 OLE DB 使用者特性。

使用特性的表和访问器声明如下:

//////////////////////////////////////////////////////////////////////
// Table and accessor declaration using attributes
// authors.h
//////////////////////////////////////////////////////////////////////

// Table class declaration
// (Note that you must provide your own connection string for db_source.)
[
   db_source(L"your connection string"),
   db_table("Authors")
]
class CAuthors
{
public:
   DBSTATUS m_dwAuIDStatus;
   DBSTATUS m_dwAuthorStatus;
   DBSTATUS m_dwYearBornStatus;
   DBLENGTH m_dwAuIDLength;
   DBLENGTH m_dwAuthorLength;
   DBLENGTH m_dwYearBornLength;
   [db_column("1", status = "m_dwAuIDStatus", length = "m_dwAuIDLength")] LONG m_AuID;
   [db_column("2", status = "m_dwAuthorStatus", length = "m_dwAuthorLength")] TCHAR m_Author[51];
   [db_column("3", status = "m_dwYearBornStatus", length = "m_dwYearBornLength")] SHORT m_YearBorn;
   void GetRowsetProperties(CDBPropSet* pPropSet)
   {
      pPropSet->AddProperty(DBPROP_CANFETCHBACKWARDS, true);
      pPropSet->AddProperty(DBPROP_CANSCROLLBACKWARDS, true);
      pPropSet->AddProperty(DBPROP_IRowsetChange, true);
   }
};

使用模板的表和访问器声明

使用模板的表和访问器声明如下。

//////////////////////////////////////////////////////////////////////
// Table and user record class declaration using templates
// authors.h
//////////////////////////////////////////////////////////////////////

// User record class declaration
class CAuthorsNoAttrAccessor
{
public:
   DWORD m_dwAuIDStatus;
   DWORD m_dwAuthorStatus;
   DWORD m_dwYearBornStatus;
   DWORD m_dwAuIDLength;
   DWORD m_dwAuthorLength;
   DWORD m_dwYearBornLength;
   LONG m_AuID;
   TCHAR m_Author[51];
   SHORT m_YearBorn;
   void GetRowsetProperties(CDBPropSet* pPropSet)
   {
      pPropSet->AddProperty(DBPROP_CANFETCHBACKWARDS, true);
      pPropSet->AddProperty(DBPROP_CANSCROLLBACKWARDS, true);
      pPropSet->AddProperty(DBPROP_IRowsetChange, true);
   }
   HRESULT OpenDataSource()
   {
      CDataSource _db;

HRESULT hr;
      hr = _db.OpenFromInitializationString(L"your connection string");
      if (FAILED(hr))
      {
#ifdef _DEBUG
         AtlTraceErrorRecords(hr);
#endif
         return hr;
      }
      return m_session.Open(_db);
   }
   void CloseDataSource()
   {
      m_session.Close();
   }
   operator const CSession&()
   {
      return m_session;
   }
   CSession m_session;
   BEGIN_COLUMN_MAP(CAuthorsNoAttrAccessor)
      COLUMN_ENTRY_LENGTH_STATUS(1, m_AuID, m_dwAuIDLength, m_dwAuIDStatus)
      COLUMN_ENTRY_LENGTH_STATUS(2, m_Author, m_dwAuthorLength, m_dwAuthorStatus)
      COLUMN_ENTRY_LENGTH_STATUS(3, m_YearBorn, m_dwYearBornLength, m_dwYearBornStatus)
   END_COLUMN_MAP()
};
class CAuthorsNoAttr : public CTable<CAccessor<CAuthorsNoAttrAccessor>>
{
public:
   HRESULT OpenAll()
   {
HRESULT hr;
      hr = OpenDataSource();
      if (FAILED(hr))
         return hr;
      __if_exists(GetRowsetProperties)
      {
         CDBPropSet propset(DBPROPSET_ROWSET);
         __if_exists(HasBookmark)
         {
            propset.AddProperty(DBPROP_IRowsetLocate, true);
         }
         GetRowsetProperties(&propset);
         return OpenRowset(&propset);
      }
      __if_not_exists(GetRowsetProperties)
      {
         __if_exists(HasBookmark)
         {
            CDBPropSet propset(DBPROPSET_ROWSET);
            propset.AddProperty(DBPROP_IRowsetLocate, true);
            return OpenRowset(&propset);
         }
      }
      return OpenRowset();
   }
   HRESULT OpenRowset(DBPROPSET *pPropSet = NULL)
   {
HRESULT hr = Open(m_session, "Authors", pPropSet);
#ifdef _DEBUG
      if(FAILED(hr))
         AtlTraceErrorRecords(hr);
#endif
      return hr;
   }
   void CloseAll()
   {
      Close();
      CloseDataSource();
   }
};

另请参阅

OLE DB 使用者特性