Używanie wielu metod dostępu w zestawie wierszy
Istnieją trzy podstawowe scenariusze, w których należy użyć wielu metod dostępu:
Wiele zestawów wierszy odczytu/zapisu. W tym scenariuszu masz tabelę z kluczem podstawowym. Chcesz mieć możliwość odczytania wszystkich kolumn w wierszu, w tym klucza podstawowego. Chcesz również zapisywać dane we wszystkich kolumnach z wyjątkiem klucza podstawowego (ponieważ nie można zapisać w kolumnie klucza podstawowego). W takim przypadku skonfigurujesz dwa metody dostępu:
Akcesorium 0 zawiera wszystkie kolumny.
Akcesorium 1 zawiera wszystkie kolumny z wyjątkiem klucza podstawowego.
Wydajność. W tym scenariuszu co najmniej jedna kolumna zawiera dużą ilość danych, na przykład grafiki, dźwięku lub plików wideo. Za każdym razem, gdy przejdziesz do wiersza, prawdopodobnie nie chcesz pobierać kolumny z dużym plikiem danych, ponieważ spowoduje to spowolnienie wydajności aplikacji.
Można skonfigurować oddzielne metody dostępu, w których pierwsza metoda dostępu zawiera wszystkie kolumny, z wyjątkiem tych z dużymi danymi, i pobiera dane z tych kolumn automatycznie; pierwszym akcesorem jest automatyczne akcesorium. Druga metoda dostępu pobiera tylko kolumnę przechowującą duże dane, ale nie pobiera danych z tej kolumny automatycznie. Możesz mieć inne metody aktualizowania lub pobierania dużych danych na żądanie.
Akcesorium 0 jest automatycznym akcesorem; pobiera wszystkie kolumny z wyjątkiem tych z dużymi danymi.
Akcesorium 1 nie jest automatycznym akcesorem; pobiera kolumnę z dużymi danymi.
Użyj argumentu automatycznego, aby określić, czy akcesorium jest akcesorem automatycznym.
Wiele kolumn ISequentialStream. W tym scenariuszu masz więcej niż jedną kolumnę przechowującą
ISequentialStream
dane. Jednak każde akcesorium jest ograniczone do jednegoISequentialStream
strumienia danych. Aby rozwiązać ten problem, skonfiguruj kilka metod dostępu, z których każdy ma jedenISequentialStream
wskaźnik.
Zwykle można tworzyć metody dostępu przy użyciu makr BEGIN_ACCESSOR i END_ACCESSOR . Można również użyć atrybutu db_accessor . (Metody dostępu zostały opisane w dalszej części Rekordy użytkowników). Makra lub atrybut określają, czy akcesorium jest automatycznym, czy nieautomatycznym akcesorem:
W przypadku automatycznego dostępu metody przenoszenia, takie jak
MoveFirst
,MoveLast
,MoveNext
iMovePrev
pobierają dane dla wszystkich określonych kolumn automatycznie. Akcesorium 0 powinno być automatycznym akcesorem.W metodzie dostępu nieautomatyczne pobieranie nie występuje, dopóki jawnie nie wywołasz metody, takiej jak
Update
,Insert
,Fetch
lubDelete
. W opisanych powyżej scenariuszach możesz nie chcieć pobrać wszystkich kolumn w każdym przeniesieniu. Można umieścić co najmniej jedną kolumnę w osobnym metodzie dostępu i zrobić to nieautomatyczne akcesorium, jak pokazano poniżej.
W poniższym przykładzie użyto wielu metod dostępu do odczytu i zapisu w tabeli zadań bazy danych pubs programu SQL Server przy użyciu wielu metod dostępu. Ten przykład jest najczęstszym zastosowaniem wielu metod dostępu; zobacz powyższy scenariusz "wiele zestawów wierszy do odczytu/zapisu".
Klasa rekordów użytkownika jest następująca. Konfiguruje dwa metody dostępu: akcesorium 0 zawiera tylko kolumnę klucza podstawowego (ID) i metodę dostępu 1 zawiera inne kolumny.
class CJobs
{
public:
enum {
sizeOfDescription = 51
};
short nID;
char szDescription[ sizeOfDescription ];
short nMinLvl;
short nMaxLvl;
DWORD dwID;
DWORD dwDescription;
DWORD dwMinLvl;
DWORD dwMaxLvl;
BEGIN_ACCESSOR_MAP(CJobs, 2)
// Accessor 0 is the automatic accessor
BEGIN_ACCESSOR(0, true)
COLUMN_ENTRY_STATUS(1, nID, dwID)
END_ACCESSOR()
// Accessor 1 is the non-automatic accessor
BEGIN_ACCESSOR(1, true)
COLUMN_ENTRY_STATUS(2, szDescription, dwDescription)
COLUMN_ENTRY_STATUS(3, nMinLvl, dwMinLvl)
COLUMN_ENTRY_STATUS(4, nMaxLvl, dwMaxLvl)
END_ACCESSOR()
END_ACCESSOR_MAP()
};
Główny kod jest następujący. Wywołanie MoveNext
automatycznie pobiera dane z identyfikatora kolumny klucza podstawowego przy użyciu metody dostępu 0. Zwróć uwagę, Insert
że metoda w pobliżu końca używa metody dostępu 1, aby uniknąć zapisywania w kolumnie klucza podstawowego.
int main(int argc, char* argv[])
{
// Initialize COM
::CoInitialize(NULL);
// Create instances of the data source and session
CDataSource source;
CSession session;
HRESULT hr = S_OK;
// Set initialization properties
CDBPropSet dbinit(DBPROPSET_DBINIT);
dbinit.AddProperty(DBPROP_AUTH_USERID, OLESTR("my_user_id"));
dbinit.AddProperty(DBPROP_INIT_CATALOG, OLESTR("pubs"));
dbinit.AddProperty(DBPROP_INIT_DATASOURCE, OLESTR("(local)"));
hr = source.Open("SQLOLEDB.1", &dbinit);
if (hr == S_OK)
{
hr = session.Open(source);
if (hr == S_OK)
{
// Ready to fetch/access data
CTable<CAccessor<CJobs>> jobs;
// Set properties for making the rowset a read/write cursor
CDBPropSet dbRowset(DBPROPSET_ROWSET);
dbRowset.AddProperty(DBPROP_CANFETCHBACKWARDS, true);
dbRowset.AddProperty(DBPROP_CANSCROLLBACKWARDS, true);
dbRowset.AddProperty(DBPROP_IRowsetChange, true);
dbRowset.AddProperty(DBPROP_UPDATABILITY,
DBPROPVAL_UP_INSERT | DBPROPVAL_UP_CHANGE |
DBPROPVAL_UP_DELETE);
hr = jobs.Open(session, "jobs", &dbRowset);
if (hr == S_OK)
{
// Calling MoveNext automatically retrieves ID
// (using accessor 0)
while(jobs.MoveNext() == S_OK)
printf_s("Description = %s\n", jobs.szDescription);
hr = jobs.MoveFirst();
if (hr == S_OK)
{
jobs.nID = 25;
strcpy_s(&jobs.szDescription[0],
jobs.sizeOfDescription,
"Developer");
jobs.nMinLvl = 10;
jobs.nMaxLvl = 20;
jobs.dwDescription = DBSTATUS_S_OK;
jobs.dwID = DBSTATUS_S_OK;
jobs.dwMaxLvl = DBSTATUS_S_OK;
jobs.dwMinLvl = DBSTATUS_S_OK;
// Insert method uses accessor 1
// (to avoid writing to the primary key column)
hr = jobs.Insert(1);
}
jobs.Close();
}
session.Close();
}
source.Close();
}
// Uninitialize COM
::CoUninitialize();
return 0;
}