使用者向导生成的类

当使用“ATL OLE DB 使用者向导”生成使用者时,可选择使用 OLE DB 模板或 OLE DB 特性。 在这两种情况下,向导都生成一个命令类和一个用户记录类。 命令类包含用于打开在向导中指定的数据源和行集合的代码。 用户记录类包含所选数据库表的列映射。 但是,每种情况下生成的代码都不同:

  • 如果选择模板使用者,则向导生成一个命令类和一个用户记录类。 命令类将具有您在向导中输入到“类”框中的名称(例如 CProducts),而用户记录类将具有“ClassNameAccessor”形式的名称(例如 CProductsAccessor)。 这两个类都放在使用者的头文件中。

  • 如果选择特性化使用者,则用户记录类将具有“_ClassNameAccessor”形式的名称并且被插入。 也就是说,将只能够在文本编辑器中查看命令类;只能够将用户记录类作为插入代码进行查看。 有关查看插入的代码的信息,请参见 调试插入的代码

下面的示例使用在 Northwind 数据库的 Products 表上创建的命令类,以演示向导生成的命令类和用户记录类使用者代码。

模板用户记录类

如果使用 OLE DB 模板(而不是 OLE DB 特性)创建 OLE DB 使用者,则向导将生成如本节所描述的代码。

列数据成员

用户记录类的第一部分包括数据成员声明以及每个数据绑定列的状态和长度数据成员。 有关这些数据成员的信息,请参见 向导生成的访问器中的字段状态数据成员

提示

如果您修改用户记录类或编写自己的使用者,则数据变量必须出现在状态变量和长度变量的前面。

提示

“ATL OLE DB 使用者向导”使用 DB_NUMERIC 类型来绑定数值数据类型。 它原来使用 DBTYPE_VARNUMERIC(其格式由 DB_VARNUMERIC 类型描述;请参见 oledb.h)。 如果不使用该向导创建使用者,建议使用 DB_NUMERIC

// Products.H : Declaration of the CProducts class

class CProductsAccessor
{
public:
   // Column data members:
   LONG m_ProductID;
   TCHAR m_ProductName[41];
   LONG m_SupplierID;
   LONG m_CategoryID;
   TCHAR m_QuantityPerUnit[21];
   CURRENCY m_UnitPrice;
   SHORT m_UnitsInStock;
   SHORT m_UnitsOnOrder;
   SHORT m_ReorderLevel;
   VARIANT_BOOL m_Discontinued;

   // Column status data members:
   DBSTATUS m_dwProductIDStatus;
   DBSTATUS m_dwProductNameStatus;
   DBSTATUS m_dwSupplierIDStatus;
   DBSTATUS m_dwCategoryIDStatus;
   DBSTATUS m_dwQuantityPerUnitStatus;
   DBSTATUS m_dwUnitPriceStatus;
   DBSTATUS m_dwUnitsInStockStatus;
   DBSTATUS m_dwUnitsOnOrderStatus;
   DBSTATUS m_dwReorderLevelStatus;
   DBSTATUS m_dwDiscontinuedStatus;

   // Column length data members:
   DBLENGTH m_dwProductIDLength;
   DBLENGTH m_dwProductNameLength;
   DBLENGTH m_dwSupplierIDLength;
   DBLENGTH m_dwCategoryIDLength;
   DBLENGTH m_dwQuantityPerUnitLength;
   DBLENGTH m_dwUnitPriceLength;
   DBLENGTH m_dwUnitsInStockLength;
   DBLENGTH m_dwUnitsOnOrderLength;
   DBLENGTH m_dwReorderLevelLength;
   DBLENGTH m_dwDiscontinuedLength;

行集合属性

下一步,向导将设置行集合属性。 如果在“ATL OLE DB 使用者向导”中选择了“更改”、“插入”或“删除”,则在此处设置适当的属性(总是设置 DBPROP_IRowsetChange,然后分别设置 DBPROPVAL_UP_CHANGE、DBPROPVAL_UP_INSERT 和/或 DBPROPVAL_UP_DELETE 中的一个或多个)。

   void GetRowsetProperties(CDBPropSet* pPropSet)
   {
      pPropSet->AddProperty(DBPROP_CANFETCHBACKWARDS, true, DBPROPOPTIONS_OPTIONAL);
      pPropSet->AddProperty(DBPROP_CANSCROLLBACKWARDS, true, DBPROPOPTIONS_OPTIONAL);
      pPropSet->AddProperty(DBPROP_IRowsetChange, true, DBPROPOPTIONS_OPTIONAL);
      pPropSet->AddProperty(DBPROP_UPDATABILITY, DBPROPVAL_UP_CHANGE | DBPROPVAL_UP_INSERT | DBPROPVAL_UP_DELETE);
   }

命令类或表类

如果指定命令类,则向导将声明该命令类;对于模板代码,该命令看起来像下面这样:

   DEFINE_COMMAND_EX(CProductsAccessor, L" \
   SELECT \
      ProductID, \
      ProductName, \
      SupplierID, \
      CategoryID, \
      QuantityPerUnit, \
      UnitPrice, \
      UnitsInStock, \
      UnitsOnOrder, \
      ReorderLevel, \
      Discontinued \
      FROM dbo.Products")

列映射

向导然后生成列绑定或列映射。 为了修复某些提供程序的一些问题,以下代码绑定列的顺序可能与提供程序所报告的顺序不同。

   BEGIN_COLUMN_MAP(CProductsAccessor)
      COLUMN_ENTRY_LENGTH_STATUS(1, m_ProductID, m_dwProductIDLength, m_dwProductIDStatus)
      COLUMN_ENTRY_LENGTH_STATUS(2, m_ProductName, m_dwProductNameLength, m_dwProductNameStatus)
      COLUMN_ENTRY_LENGTH_STATUS(3, m_SupplierID, m_dwSupplierIDLength, m_dwSupplierIDStatus)
      COLUMN_ENTRY_LENGTH_STATUS(4, m_CategoryID, m_dwCategoryIDLength, m_dwCategoryIDStatus)
      COLUMN_ENTRY_LENGTH_STATUS(5, m_QuantityPerUnit, m_dwQuantityPerUnitLength, m_dwQuantityPerUnitStatus)
      _COLUMN_ENTRY_CODE(6, DBTYPE_CY, _SIZE_TYPE(m_UnitPrice), 0, 0, offsetbuf(m_UnitPrice), offsetbuf(m_dwUnitPriceLength), offsetbuf(m_dwUnitPriceStatus))
      COLUMN_ENTRY_LENGTH_STATUS(7, m_UnitsInStock, m_dwUnitsInStockLength, m_dwUnitsInStockStatus)
      COLUMN_ENTRY_LENGTH_STATUS(8, m_UnitsOnOrder, m_dwUnitsOnOrderLength, m_dwUnitsOnOrderStatus)
      COLUMN_ENTRY_LENGTH_STATUS(9, m_ReorderLevel, m_dwReorderLevelLength, m_dwReorderLevelStatus)
      _COLUMN_ENTRY_CODE(10, DBTYPE_BOOL, _SIZE_TYPE(m_Discontinued), 0, 0, offsetbuf(m_Discontinued), offsetbuf(m_dwDiscontinuedLength), offsetbuf(m_dwDiscontinuedStatus))
   END_COLUMN_MAP()
};

类声明

最后,向导生成如下所示的命令类声明:

class CProducts : public CCommand<CAccessor<CProductsAccessor> >

特性插入的用户记录类

如果使用数据库特性(db_commanddb_table)创建 OLE DB 使用者,则这些特性将插入一个用户记录类,其名称采用“_ClassNameAccessor”形式。例如,如果将命令类命名为 COrders,则用户记录类为 _COrdersAccessor。 虽然用户记录类出现在“类视图”中,但双击它时却会定位到头文件中的命令或表类。 在这些情况下,您只能通过查看特性插入的代码来查看实际的用户记录类声明。

如果在特性化的使用者中添加或重写方法,则会有潜在的问题。 例如,可以将 _COrdersAccessor 构造函数添加到 COrders 声明,但是请注意,这实际上是将构造函数添加到插入的 COrdersAccessor 类。 这样的构造函数可初始化列/参数,但是不能用这种方式创建复制构造函数,这是因为它无法直接实例化 COrdersAccessor 对象。 如果需要在 COrders 类上直接有一个构造函数(或其他方法),则建议您定义一个从 COrders 中派生的新类并在其中添加必要的方法。

在下面的示例中,向导生成了 COrders 类的声明,但是用户记录类 COrdersAccessor 未出现,原因是特性将插入它。

#define _ATL_ATTRIBUTES
#include <atlbase.h>
#include <atldbcli.h>
[
   db_source(L"your connection string"),
   db_command(L"Select ShipName from Orders;")
]
class COrders
{
public:

   // COrders()            // incorrect constructor name
   _COrdersAccessor()      // correct constructor name
   {
   }
      [db_column(1) ] TCHAR m_ShipName[41];
   };

插入的命令类声明看起来像这样:

class CProducts : public CCommand<CAccessor<_CProductsAccessor> >

大部分插入的代码与模板化版本相同或类似于模板化版本。 主要差别是插入的方法,详见 使用者向导生成的方法 中的说明。

有关查看插入的代码的信息,请参见 调试插入的代码

请参见

概念

使用向导创建 OLE DB 使用者