コンシューマ ウィザードで生成されたクラス
更新 : 2007 年 11 月
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 のうち 1 つ以上が設定されます。
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_command または db_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> >
挿入されたコードの大半は、テンプレートを使用する場合と同じか、または似ています。主な違いは、挿入されたメソッドにあります。これについては、「コンシューマ ウィザードで生成されたメソッド」で説明しています。
挿入されたコードの表示については、「挿入されたコードのデバッグ」を参照してください。