Używanie wielu akcesorów zestawu wierszy
Istnieją trzy podstawowe scenariusze, w których trzeba użyć wielu akcesorów:
Wiele wierszy odczytu i zapisu. W tym scenariuszu należy tabeli z kluczem podstawowym.Chcesz odczytać wszystkie kolumny w wierszu, w tym klucza podstawowego.Ma również mieć możliwość zapisywania danych w kolumnach klucza podstawowego z wyjątkiem (ponieważ nie można zapisać kolumny klucza podstawowego).W tym przypadku można zdefiniować dwa akcesorów
Akcesor 0 zawiera wszystkie kolumny.
Akcesor 1 zawiera wszystkie kolumny klucza podstawowego z wyjątkiem.
Wydajność. W tym scenariuszu jeden lub więcej kolumn zawierają duże ilości danych, na przykład grafiki, pliki dźwiękowe i wideo.Każdorazowo, aby przenieść wiersz, prawdopodobnie chcesz pobrać kolumny z pliku danych duże, ponieważ zaawansowana tak może spowolnić wydajność aplikacji.
Można skonfigurować oddzielne akcesory, w których pierwszy akcesor zawiera wszystkie kolumny, z wyjątkiem jednego z dużych danych i go pobiera dane z tych kolumn automatycznie; jest to akcesor auto.Drugi akcesor pobiera tylko kolumny zawierające duże, ale go nie pobierać dane z tej kolumny automatycznie.Może mieć inne metody, zaktualizować lub pobrania dużej danych na żądanie.
Akcesor 0 jest automatyczne akcesora operacji; pobiera wszystkie kolumny z wyjątkiem jednego z dużych danych.
Akcesor 1 nie jest automatyczne akcesora operacji; pobiera kolumny z danymi duże.
Aby określić, czy obiekt jest to akcesor auto, należy użyć argumentu auto.
Wiele kolumn ISequentialStream. W tym scenariuszu masz więcej niż jednej kolumny zawierające ISequentialStream danych.Jednakże każda akcesor jest tylko jeden ISequentialStream strumienia danych.Aby rozwiązać ten problem, skonfigurować kilka akcesorów każdy zawierający jeden ISequentialStream wskaźnik.
Zwykle utworzyć akcesorów za pomocą BEGIN_ACCESSOR i END_ACCESSOR makr.Można również użyć db_accessor atrybut.(Akcesory to opisano w Rekordów użytkowników.) Makra lub atrybut należy określić, czy akcesor jest automatyczne lub akcesora-automatyczne:
W akcesor automatyczne przenoszenie metody takie jak MoveFirst, MoveLast, MoveNext, i MovePrev pobierania danych dla kolumny wszystkie określone automatycznie.Akcesor 0 powinna być automatyczne akcesor.
W akcesor nieautomatyczne, pobieranie nie występuje do momentu jawnego wywołania metody takie jak Aktualizacja, wstawić, Fetch, lub usunąć.W scenariuszach opisano powyżej nie można pobrać wszystkie kolumny na każdy ruch.Można umieścić jeden lub więcej kolumn w oddzielnych akcesor i należy, że akcesor nieautomatyczne, jak pokazano poniżej.
Poniższy przykład używa wielu akcesorów do odczytu i zapisu do bazy danych pubs SQL Server przy użyciu wielu akcesorów tabeli zadań.Jest to najczęściej wielu akcesorów; zobacz scenariusz "wiele zestawów wierszy odczytu i zapisu" powyżej.
Klasa rekordu użytkownika jest następująca:Konfiguruje dwa akcesorów: 0 akcesora zawiera tylko kolumny klucza podstawowego (ID) i akcesor 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 wygląda następująco:Wywołanie MoveNext automatycznie pobiera dane z Identyfikatora kolumny klucza podstawowego, przy użyciu akcesor 0.Uwaga jak wstawić metodę akcesora wykorzystania końcowego 1, aby uniknąć pisania do kolumny klucza podstawowego w pobliżu.
int main(int argc, char* argv[])
{
// Initalize 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;
}