消費者精靈產生的類別
當您使用 ATL OLE DB 消費者精靈來產生消費者時,必須選擇使用 OLE DB 樣板或 OLE DB 屬性。在這兩種狀況中,精靈都會產生一個命令類別和使用者資料錄類別。命令類別包含了可以開啟在精靈中指定的資料來源和資料列集的程式碼。使用者資料錄類別包含了選取資料庫資料表的資料行對應。不過,每種狀況所產生的程式碼都不一樣:
若您選取使用樣板的消費者,精靈將產生一命令類別和一使用者資料錄類別。命令類別會擁有您輸入至精靈的 [類別] 方塊內的名稱 (例如 CProducts),而使用者資料錄類別會具有「ClassName 存取子」形式的名稱 (例如 CProductsAccessor)。這兩個類別都放在消費者的標頭檔 (Header File) 內。
若您選取一屬性化的消費者,使用者資料錄類別將具有 "_ClassNameAccessor" 形式的名稱,並將被插入。也就是說,您可在文字編輯器內只檢視命令類別;您可採插入的程式碼形式來檢視使用者資料錄類別。如需檢視插入程式碼的詳細資訊,請參閱偵錯插入程式碼。
下列範例使用建立於 Northwind 資料庫的 Products 資料表內的命令類別,以示範精靈產生的命令類別和使用者資料錄類別的消費者程式碼。
使用樣板的使用者資料錄類別
若您使用 OLE DB 樣板 (而非 OLE DB 屬性) 來建立 OLE DB 消費者,精靈便會產生本章節所說明的程式碼。
資料行資料成員
使用者資料錄類別的第一部分,包含了資料成員宣告和每個資料繫結資料行的狀態與長度。如需這些資料成員的詳細資料,請參閱在精靈產生的存取子中的欄位狀態資料成員。
注意事項 |
---|
如果您修改使用者資料錄類別或撰寫自己的消費者,資料變數必須出現在狀態和長度變數之前。 |
注意事項 |
---|
ATL OLE DB 消費者精靈會使用 DB_NUMERIC 型別來繫結數字 (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_command 或 db_table) 建立了 OLE DB 消費者,該屬性便會以 "_ClassNameAccessor" 名稱格式插入使用者資料錄類別。例如,如果您將命令類別命名為 COrders,該使用者資料錄類別就會是 _COrdersAccessor。雖然使用者資料錄類別會出現在 [類別檢視] 中,在標頭檔 (Header File) 中按兩下滑鼠也可以巡覽命令或資料表類別。在這種情況下,您只能透過檢視插入屬性的程式碼檢視實質的使用者資料錄類別宣告。
如果您在屬性化的消費者中加入或覆寫方法,可能會使問題變得很複雜。例如,您可將 _COrdersAccessor 建構函式 (Constructor) 加入至 COrders 宣告,不過請注意,事實上這會加入建構函式至插入的 COrdersAccessor 類別內。這類建構函式可初始化資料行/參數,但是您不能以此方法建立一複製建構函式 (Copy Constructor),因為它不能直接執行個體化 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> >
大部分插入的程式碼會與樣板版本相同或相類似。主要的差異在於插入的方法,在消費者精靈產生的方法中有說明插入的方法。
如需檢視插入程式碼的詳細資訊,請參閱偵錯插入程式碼。