Vom Consumer-Assistenten generierte Klassen
Wenn Sie den ATL-OLE DB-Consumer-Assistenten zum Generieren eines Consumers verwenden, können Sie wahlweise OLE DB-Vorlagen oder OLE DB-Attribute verwenden.In beiden Fällen generiert der Assistent eine Befehlsklasse und eine Benutzerdatensatz-Klasse.Die Befehlsklasse enthält Code zum Öffnen der im Assistenten angegebenen Datenquelle und des im Assistenten angegebenen Rowsets.Die Benutzerdatensatz-Klasse enthält eine Spaltenzuordnung für die ausgewählte Datenbanktabelle.Der jeweils generierte Code sieht in beiden Fällen jedoch unterschiedlich aus:
Wenn Sie einen aus einer Vorlage gebildeten Consumer auswählen, generiert der Assistent eine Befehlsklasse und eine Benutzerdatensatz-Klasse.Die Befehlsklasse trägt den Namen, den Sie im Assistenten im Feld Klasse eingegeben haben (in diesem Fall CProducts), und die Benutzerdatensatz-Klasse trägt einen Namen im Format KlassennameAccessor (in diesem Fall CProductsAccessor).Beide Klassen werden in der Headerdatei des Consumers gespeichert.
Wenn Sie einen Consumer mit Attributen auswählen, weist die Benutzerdatensatz-Klasse einen Namen im Format _KlassennameAccessor auf und wird eingefügt.Das bedeutet, dass Sie nur die Befehlsklasse im Text-Editor anzeigen können. Die Benutzerdatensatz-Klasse hingegen kann nur als eingefügter Code angezeigt werden.Informationen zum Anzeigen von eingefügtem Code finden Sie unter Debuggen von eingefügtem Code.
In den folgenden Beispielen wird anhand einer für die Tabelle Products der Datenbank Northwind erstellten Befehlsklasse der vom Assistenten generierte Consumercode für die Befehlsklasse und die Benutzerdatensatz-Klasse demonstriert.
Aus einer Vorlage gebildete Benutzerdatensatz-Klassen
Wenn Sie einen OLE DB-Consumer unter Verwendung der OLE DB-Vorlagen (also nicht mit den OLE DB-Attributen) erstellen, generiert der Assistent den Code, wie in diesem Abschnitt beschrieben.
Spaltendatenmember
Der erste Teil der Benutzerdatensatzklasse enthält die Datenmemberdeklarationen sowie die Datenmember für Status und Länge für jede datengebundene Spalte.Informationen zu diesen Datenmembern finden Sie unter Feldstatus-Datenmember in vom Assistenten generierten Accessoren.
Hinweis |
---|
Wenn Sie die Benutzerdatensatz-Klasse verändern oder einen eigenen Consumer schreiben, müssen die Datenvariablen vor den Status- und Längenvariablen stehen. |
Hinweis |
---|
Der ATL OLE DB-Consumer-Assistent verwendet zum Binden numerischer Datentypen den Typ DB_NUMERIC .Früher verwendete er DBTYPE_VARNUMERIC (das entsprechende Format wird vom DB_VARNUMERIC-Typ beschrieben; siehe Oledb.h).Wenn Sie Consumer ohne den Assistenten erstellen, wird empfohlen, DB_NUMERIC zu verwenden. |
// 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;
Rowseteigenschaften
Als Nächstes legt der Assistent die Rowseteigenschaften fest.Wenn Sie im ATL-OLE DB-Consumer-Assistenten Ändern, Einfügen oder Löschen ausgewählt haben, werden die entsprechenden Eigenschaften hier festgelegt (DBPROP_IRowsetChange ist immer gesetzt und zusätzlich DBPROPVAL_UP_CHANGE, DBPROPVAL_UP_INSERT und/oder 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);
}
Befehls- oder Tabellenklasse
Wenn Sie eine Befehlsklasse festlegen, deklariert der Assistent diese. Bei aus einer Vorlage gebildetem Code sieht der Befehl folgendermaßen aus:
DEFINE_COMMAND_EX(CProductsAccessor, L" \
SELECT \
ProductID, \
ProductName, \
SupplierID, \
CategoryID, \
QuantityPerUnit, \
UnitPrice, \
UnitsInStock, \
UnitsOnOrder, \
ReorderLevel, \
Discontinued \
FROM dbo.Products")
Spaltenzuordnung
Dann generiert der Assistent die Spaltenbindungen bzw. Spaltenzuordnung.Zur Behebung verschiedener Probleme mit bestimmten Anbietern werden im folgenden Code Spalten u. U. in einer anderen Reihenfolge gebunden, als vom Anbieter angegeben.
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()
};
Klassendeklaration
Schließlich generiert der Assistent eine Befehlsklassendeklaration entsprechend der folgenden:
class CProducts : public CCommand<CAccessor<CProductsAccessor> >
Benutzerdatensatz-Klassen mit Attributbeteiligung
Beim Erstellen eines OLE DB-Consumers mithilfe der Datenbankattribute (db_command oder db_table) erstellen die Attribute eine Benutzerdatensatz-Klasse mit einem Namen der Form "_KlassennameAccessor." Wenn Sie die Befehlsklasse beispielsweise COrders genannt haben, erhält die Benutzerdatensatz-Klasse den Namen _COrdersAccessor.Obwohl die Benutzerdatensatz-Klasse in der Klassenansicht angezeigt wird, können Sie dafür durch Doppelklicken zur Befehls- oder Tabellenklasse in der Headerdatei navigieren.In diesen Fällen können Sie die tatsächliche Deklaration der Benutzerdatensatz-Klasse nur anzeigen, indem Sie den durch die Attribute eingefügten Code anzeigen.
Es können Komplikationen auftreten, wenn Sie Methoden in Consumern mit Attributen hinzufügen oder überschreiben.So könnten Sie z. B. der COrders-Deklaration einen _COrdersAccessor-Konstruktor hinzufügen, dabei wird jedoch tatsächlich der eingefügten COrdersAccessor-Klasse ein Konstruktor hinzugefügt.Ein solcher Konstruktor kann zwar die Spalten/Parameter initialisieren, Sie können auf diese Weise jedoch keinen Kopierkonstruktor erstellen, da das COrdersAccessor-Objekt nicht direkt instanziiert werden kann.Wenn Sie einen Konstruktor (oder eine andere Methode) direkt für die COrders-Klasse benötigen, empfiehlt es sich, eine neue, von COrders abgeleitete Klasse zu definieren und dieser die erforderlichen Methoden hinzuzufügen.
Im folgenden Beispiel hat der Assistent eine Deklaration für die COrders-Klasse generiert, die COrdersAccessor-Benutzerdatensatz-Klasse wird jedoch nicht angezeigt, da die Attribute diese einfügen.
#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];
};
Die eingefügte Befehlsklassendeklaration sieht folgendermaßen aus:
class CProducts : public CCommand<CAccessor<_CProductsAccessor> >
Der größte Teil des eingefügten Codes ist derselbe wie in der Version aus der Vorlage oder ihm ähnlich.Die Hauptunterschiede liegen in den eingefügten Methoden, die unter Vom Consumer-Assistenten generierte Methoden beschrieben werden.
Informationen zum Anzeigen von eingefügtem Code finden Sie unter Debuggen von eingefügtem Code.