Classes de consommateur générées par l'Assistant
Si vous utilisez l'Assistant Consommateur OLEDB ATL pour générer un consommateur, vous aurez le choix entre les options Modèles OLE DB et Attributs OLE DB. Dans les deux cas, l'Assistant génère une classe de commande et une classe d'enregistrement utilisateur. La classe de commande contient du code permettant d'ouvrir la source de données et le jeu de lignes que vous avez spécifiés dans l'Assistant. La classe d'enregistrement utilisateur contient un mappage de colonnes de la table de base de données que vous avez sélectionnée. Cependant, le code généré diffère à chaque fois :
Si vous sélectionnez un consommateur avec modèles, l'Assistant génère une classe de commande et une classe d'enregistrement utilisateur. La classe de commande prendra le nom que vous entrez dans la zone Classe de l'Assistant (par exemple, CProducts), et la classe d'enregistrement utilisateur aura un nom sous la forme « NomClasseAccessor » (par exemple, CProductsAccessor). Les deux classes sont placées dans le fichier d'en-tête du consommateur.
Si vous sélectionnez un consommateur avec attributs, la classe d'enregistrement utilisateur portera un nom ayant la forme « _NomClasseAccessor » et sera injectée. Autrement dit, vous pouvez afficher seulement la classe de commande dans l'éditeur de texte, et vous pouvez consulter la classe d'enregistrement utilisateur uniquement comme code injecté. Pour plus d'informations sur l'affichage de code injecté, consultez Débogage de code injecté.
Les exemples suivants utilisent une classe de commande créée dans la table Products de la base de données Northwind afin d'illustrer le code du consommateur généré par l'Assistant pour la classe de commande et la classe d'enregistrement utilisateur.
Classes d'enregistrement utilisateur avec modèles
Si vous créez un consommateur OLE DB en utilisant les modèles OLE DB (plutôt que les attributs OLE DB), l'Assistant génère le code comme expliqué dans cette section.
Données membres de type colonne
La première partie de la classe d'enregistrement utilisateur comprend les déclarations des données membres et les données membres indiquant l'état et la longueur de chaque colonne liée aux données. Pour plus d'informations sur ces données membres, consultez Données membres de l'état des champs dans les accesseurs générés par l'Assistant.
Notes
Si vous modifiez la classe d'enregistrement utilisateur ou écrivez votre propre consommateur, les variables de données doivent précéder les variables d'état et de longueur.
Notes
L'Assistant Consommateur OLE DB ATL utilise le type DB_NUMERIC pour lier des types de données numériques. Il utilisait avant DBTYPE_VARNUMERIC (dont le format est décrit par le type DB_VARNUMERIC ; consultez Oledb.h). Si vous n'utilisez pas l'Assistant pour créer des consommateurs, il est recommandé d'utiliser 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;
Propriétés du jeu de lignes
Ensuite, les propriétés du jeu de lignes sont définies. Si vous avez sélectionné Modifier, Insérer ou Supprimer dans l'Assistant Consommateur OLE DB ATL, les propriétés appropriées sont définies ici (DBPROP_IRowsetChange est toujours définie, puis une ou plusieurs propriétés DBPROPVAL_UP_CHANGE, DBPROPVAL_UP_INSERT et/ou DBPROPVAL_UP_DELETE, respectivement).
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);
}
Classe de commande ou de table
Si vous spécifiez une classe de commande, l'Assistant déclare la classe de commande ; pour le code avec modèles, la commande se présente comme suit :
DEFINE_COMMAND_EX(CProductsAccessor, L" \
SELECT \
ProductID, \
ProductName, \
SupplierID, \
CategoryID, \
QuantityPerUnit, \
UnitPrice, \
UnitsInStock, \
UnitsOnOrder, \
ReorderLevel, \
Discontinued \
FROM dbo.Products")
Mappage de colonnes
L'Assistant génère ensuite les liens des colonnes ou mappage de colonnes. Pour résoudre plusieurs problèmes avec certains fournisseurs, le code suivant peut lier les colonnes dans un ordre différent de celui indiqué par le fournisseur.
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()
};
Déclaration de classe
Enfin, l'Assistant génère une déclaration de classe de commande, telle que la suivante :
class CProducts : public CCommand<CAccessor<CProductsAccessor> >
Classes d'enregistrement utilisateur injectées par les attributs
Si vous créez un consommateur OLE DB en utilisant les attributs de base de données (db_command ou db_table), les attributs injectent une classe d'enregistrement utilisateur qui porte un nom présentant la forme suivante : « _NomClasseAccessor ». Par exemple, si vous avez nommé votre classe de commande COrders, la classe d'enregistrement utilisateur sera _COrdersAccessor. Bien que la classe d'enregistrement utilisateur apparaisse dans l'affichage de classes, il suffit de double-cliquer dessus pour atteindre plutôt la classe de commande ou de table dans le fichier d'en-tête. En ces cas, vous pouvez seulement afficher la déclaration réelle de la classe d'enregistrement utilisateur en visualisant le code injecté par les attributs.
Vous risquez de rencontrer des problèmes si vous ajoutez ou substituez des méthodes dans des consommateurs avec attributs. Par exemple, vous pouvez ajouter un constructeur _COrdersAccessor à la déclaration COrders ; notez, cependant, que ce faisant vous ajoutez en fait un constructeur à la classe COrdersAccessor injectée. Un tel constructeur peut initialiser les colonnes/paramètres, mais vous ne pouvez pas créer un constructeur de copie de cette façon, car il ne peut pas instancier directement l'objet COrdersAccessor. Si vous avez besoin d'un constructeur (ou d'une méthode) directement sur la classe COrders, il est recommandé de définir une nouvelle classe dérivant de COrders et d'y ajouter les méthodes nécessaires.
Dans l'exemple suivant, l'Assistant a généré une déclaration pour la classe COrders, mais la classe d'enregistrement utilisateur COrdersAccessor n'apparaît pas, car elle est injectée par les attributs.
#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];
};
La déclaration de classe de commande injectée se présente de la façon suivante :
class CProducts : public CCommand<CAccessor<_CProductsAccessor> >
L'essentiel du code injecté est identique ou similaire à la version avec attributs. Les différences essentielles résident dans les méthodes injectées, lesquelles sont décrites dans Méthodes de consommateur générées par l'Assistant.
Pour plus d'informations sur l'affichage de code injecté, consultez Débogage de code injecté.