Klasy konsumentów generowane przez kreatora
Kreator konsumenta OLE DB ATL nie jest dostępny w programie Visual Studio 2019 i nowszych wersjach. Nadal można dodać funkcjonalność ręcznie.
Jeśli do wygenerowania użytkownika używasz Kreatora konsumenta OLE DB ATL, możesz użyć szablonów OLE DB lub atrybutów OLE DB. W obu przypadkach kreator generuje klasę poleceń i klasę rekordów użytkownika. Klasa poleceń zawiera kod umożliwiający otwarcie źródła danych i zestawu wierszy określonego w kreatorze. Klasa rekordów użytkownika zawiera mapę kolumn dla wybranej tabeli bazy danych. Jednak wygenerowany kod różni się w każdym przypadku:
Jeśli wybierzesz szablonowego konsumenta, kreator wygeneruje klasę poleceń i klasę rekordów użytkownika. Klasa poleceń będzie miała nazwę wprowadzoną w polu Klasa w kreatorze (na przykład
CProducts
), a klasa rekordów użytkownika będzie miała nazwę formularza "KlasaNazwadostępu" (na przykładCProductsAccessor
). Obie klasy są umieszczane w pliku nagłówkowym odbiorcy.Jeśli wybierzesz przypisanego konsumenta, klasa rekordów użytkownika będzie miała nazwę formularza "_ClassNameAccessor" i zostanie wstrzyknięta. Oznacza to, że będzie można wyświetlić tylko klasę poleceń w edytorze tekstów; Klasę rekordów użytkownika można wyświetlić tylko jako kod wstrzyknięty. Aby uzyskać informacje na temat wyświetlania wprowadzonego kodu, zobacz Debugowanie wprowadzonego kodu.
W poniższych przykładach użyto klasy poleceń utworzonej Northwind
w Products
tabeli bazy danych, aby zademonstrować kod odbiorcy wygenerowany przez kreatora dla klasy poleceń i klasy rekordów użytkownika.
Klasy rekordów użytkownika szablonu
Jeśli tworzysz użytkownika OLE DB przy użyciu szablonów OLE DB (a nie atrybutów OLE DB), kreator generuje kod zgodnie z opisem w tej sekcji.
Składowe danych kolumn
Pierwsza część klasy rekordów użytkownika zawiera deklaracje składowych danych oraz składowe stanu i długości danych dla każdej kolumny powiązanej z danymi. Aby uzyskać informacje o tych elementach członkowskich danych, zobacz Składowe danych stanu pola w metodach dostępu generowanych przez kreatora.
Uwaga
Jeśli zmodyfikujesz klasę rekordów użytkownika lub zapiszesz własnego konsumenta, zmienne danych muszą znajdować się przed zmiennymi stanu i długości.
Uwaga
Kreator konsumenta OLE DB ATL używa DB_NUMERIC
typu do powiązania typów danych liczbowych. Wcześniej używany DBTYPE_VARNUMERIC
(format, którego format jest opisany przez DB_VARNUMERIC
typ; zobacz Oledb.h). Jeśli nie używasz kreatora do tworzenia użytkowników, zaleca się użycie polecenia 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;
Właściwości zestawu wierszy
Następnie kreator ustawia właściwości zestawu wierszy. W przypadku wybrania opcji Zmień, Wstaw lub Usuń w Kreatorze konsumenta OLE DB ATL odpowiednie właściwości są ustawione w tym miejscu (DBPROP_IRowsetChange jest zawsze ustawiana, a następnie co najmniej jedna DBPROPVAL_UP_CHANGE, DBPROPVAL_UP_INSERT i/lub DBPROPVAL_UP_DELETE, odpowiednio).
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);
}
Command or Table Class
Jeśli określisz klasę poleceń, kreator deklaruje klasę poleceń; w przypadku kodu szablonu polecenie wygląda następująco:
DEFINE_COMMAND_EX(CProductsAccessor, L" \
SELECT \
ProductID, \
ProductName, \
SupplierID, \
CategoryID, \
QuantityPerUnit, \
UnitPrice, \
UnitsInStock, \
UnitsOnOrder, \
ReorderLevel, \
Discontinued \
FROM dbo.Products")
Mapa kolumn
Następnie kreator generuje powiązania kolumn lub mapę kolumn. Aby rozwiązać kilka problemów z niektórymi dostawcami, poniższy kod może powiązać kolumny w innej kolejności niż zgłoszone przez dostawcę.
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()
};
Deklaracja klasy
Na koniec kreator generuje deklarację klasy poleceń, taką jak:
class CProducts : public CCommand<CAccessor<CProductsAccessor>>
Klasy rekordów użytkownika wstrzykiwane przez atrybuty
Jeśli tworzysz użytkownika OLE DB przy użyciu atrybutów bazy danych (db_command lub db_table), atrybuty wprowadzają klasę rekordów użytkownika o nazwie formularza "_ClassNameAccessor". Jeśli na przykład nazwano klasę COrders
poleceń , klasa rekordu użytkownika będzie mieć wartość _COrdersAccessor
. Mimo że klasa rekordów użytkownika jest wyświetlana w widoku klasy, dwukrotne kliknięcie go powoduje przejście do polecenia lub klasy tabeli w pliku nagłówka. W takich przypadkach można wyświetlić tylko rzeczywistą deklarację klasy rekordów użytkownika, wyświetlając kod wstrzykiwany atrybutem.
Mogą wystąpić potencjalne komplikacje, jeśli dodasz lub przesłonisz metody dla użytkowników przypisanych. Można na przykład dodać _COrdersAccessor
konstruktor do COrders
deklaracji, ale należy pamiętać, że w rzeczywistości dodaje konstruktor do wstrzykiwanej COrdersAccessor
klasy. Taki konstruktor może zainicjować kolumny/parametry, ale nie można w ten sposób utworzyć konstruktora kopiowania, ponieważ nie może bezpośrednio utworzyć COrdersAccessor
wystąpienia obiektu. Jeśli potrzebujesz konstruktora (lub innej metody) bezpośrednio w COrders
klasie, zaleca się zdefiniowanie nowej klasy pochodnej i COrders
dodanie niezbędnych metod.
W poniższym przykładzie kreator generuje deklarację dla klasy COrders
, ale klasa COrdersAccessor
rekordów użytkownika nie jest wyświetlana, ponieważ atrybuty go wstrzykiwają.
#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];
};
Wstrzyknięta deklaracja klasy poleceń wygląda następująco:
class CProducts : public CCommand<CAccessor<_CProductsAccessor>>
Większość wprowadzonego kodu jest taka sama jak lub podobna do wersji szablonu. Główne różnice dotyczą metod wstrzykiwanych, które opisano w temacie Metody generowane przez kreatora odbiorców.
Aby uzyskać informacje na temat wyświetlania wprowadzonego kodu, zobacz Debugowanie wprowadzonego kodu.