Для завершення вашої реалізації на IRowsetLocate інтерфейс, ви повинні виконати, закладки. Закладки є індексами набір рядків, які дозволяють високошвидкісний доступ до даних. Постачальник визначає, що закладки можна однозначно ідентифікувати рядок. У цьому прикладі використовується індекс на m_rgAgentInfo масиву.
Постачальник може отримувати закладки в будь-якому форматі. На переконайтесь, що закладки вказано:
CAgentMan , визначає бути DWORD, запис dwBookmark . Довжина однобайтові використовується для спеціальних закладки, DBMRK_FIRST і DBMRK_LAST.)Після перевірки як закладки, (по одному на кожен рядок), телефонуйте порівняти метод, який займає два закладки та визначає, якщо одна є менше, більше, ніж, або дорівнює іншого.
Для вилучення рядків, здійснювати функції GetRowsAt і GetRowsByBookmark.
GetRowsAt працює так само, як на IRowset::GetNextRows метод, за винятком, що він використовує закладку для вибірки даних. Це підтверджує закладку а потім викликає IRowsetImpl::GetNextRows отримати рядки.
GetRowsByBookmark вибирає рядок за кількість місць. Його можна використовувати для вилучення певних рядків. GetRowsByBookmark перевіряє кожен закладок, а потім вибирає рядок за номером IRowsetImpl::CreateRow, яка створює новий рядок, якщо це необхідно. Рядки повертаються в масиві вказали наrghRows.
(Оскільки цей приклад використовує простий фіксованої довжини закладки, він не виконує IRowsetLocate::Hash методу. Якщо ваш провайдер використовує змінної довжини закладки або ресурсомістких обчислень дорогих закладки, ви можете здійснювати IRowsetLocate::Hash методу як добре.)
Повне виконання IRowsetLocateImpl виглядає наступним чином:
/////////////////////////////////////////////////////////////////////////// RowLoc.h
// class IRowsetLocateImpl
template <class T>
class ATL_NO_VTABLE IRowsetLocateImpl : public IRowsetImpl<T>
{
public:
STDMETHOD (Compare)(HCHAPTER hReserved, ULONG cbBookmark1,
const BYTE * pBookmark1, ULONG cbBookmark2, const BYTE * pBookmark2,
DBCOMPARE * pComparison)
{
ATLTRACE("IRowsetLocateImpl::Compare");
HRESULT hr = ValidateBookmark(cbBookmark1, pBookmark1);
if (hr != S_OK)
return hr;
hr = ValidateBookmark(cbBookmark2, pBookmark2);
if (hr != S_OK)
return hr;
// Return the value based on the bookmark values
if (*pBookmark1 == *pBookmark2)
*pComparison = DBCOMPARE_EQ;
if (*pBookmark1 < *pBookmark2)
*pComparison = DBCOMPARE_LT;
if (*pBookmark1 > *pBookmark2)
*pComparison = DBCOMPARE_GT;
return S_OK;
}
STDMETHOD (GetRowsAt)(HWATCHREGION hReserved1, HCHAPTER hReserved2,
ULONG cbBookmark, const BYTE * pBookmark, LONG lRowsOffset,
LONG cRows, ULONG * pcRowsObtained, HROW ** prghRows)
{
ATLTRACE("IRowsetLocateImpl::GetRowsAt");
T* pT = (T*)this;
// Check bookmark
HRESULT hr = ValidateBookmark(cbBookmark, pBookmark);
if (hr != S_OK)
return hr;
// Check the other pointers
if (pcRowsObtained == NULL || prghRows == NULL)
return E_INVALIDARG;
// Set the current row position to the bookmark. Handle any
// normal values
pT->Lock();
LONG iRowsetTemp = m_iRowset; // Cache the current rowset
m_iRowset = *pBookmark;
if (*pBookmark == DBBMK_FIRST)
m_iRowset = 1;
if (*pBookmark == DBBMK_LAST)
m_iRowset = pT->m_rgRowData.GetSize();
// Call IRowsetImpl::GetNextRows to actually get the rows.
hr = GetNextRows(hReserved2, lRowsOffset,
cRows, pcRowsObtained, prghRows);
m_iRowset = iRowsetTemp;
pT->Unlock();
return hr;
}
STDMETHOD (GetRowsByBookmark)(HCHAPTER hReserved, ULONG cRows,
const ULONG rgcbBookmarks[], const BYTE * rgpBookmarks[],
HROW rghRows[], DBROWSTATUS rgRowStatus[])
{
HRESULT hr = S_OK;
ATLTRACE("IRowsetLocateImpl::GetRowsByBookmark");
T* pT = (T*)this;
if (rgcbBookmarks == NULL || rgpBookmarks == NULL || rghRows == NULL)
return E_INVALIDARG;
if (cRows == 0)
return S_OK; // No rows fetched in this case.
bool bErrors = false;
pT->Lock();
for (ULONG l=0; l<cRows; l++)
{
// Validate each bookmark before fetching the row. Note, it is
// an error for the bookmark to be one of the standard values
hr = ValidateBookmark(rgcbBookmarks[l], rgpBookmarks[l]);
if (hr != S_OK)
{
bErrors = TRUE;
if (rgRowStatus != NULL)
{
rgRowStatus[l] = DBROWSTATUS_E_INVALID;
continue;
}
}
// Fetch the validated row
ULONG ulRowsObtained = 0;
if (CreateRow((long)*rgpBookmarks[l], ulRowsObtained, &rghRows[l]) != S_OK)
{
bErrors = TRUE;
}
else
{
if (rgRowStatus != NULL)
rgRowStatus[l] = DBROWSTATUS_S_OK;
}
}
pT->Unlock();
if (bErrors)
return DB_S_ERRORSOCCURRED;
else
return hr;
}
STDMETHOD (Hash)(HCHAPTER hReserved, ULONG cBookmarks,
const ULONG rgcbBookmarks[], const BYTE * rgpBookmarks[],
DWORD rgHashedValues[], DBROWSTATUS rgBookmarkStatus[])
{
ATLTRACENOTIMPL("IRowsetLocateImpl::GetRowsByBookmark");
}
// Implementation
protected:
HRESULT ValidateBookmark(ULONG cbBookmark, const BYTE* pBookmark)
{
T* pT = (T*)this;
if (cbBookmark == 0 || pBookmark == NULL)
return E_INVALIDARG;
// All of our bookmarks are DWORDs, if they are anything other than
// sizeof(DWORD) then we have an invalid bookmark
if ((cbBookmark != sizeof(DWORD)) && (cbBookmark != 1))
{
ATLTRACE("Bookmarks are invalid length, should be DWORDs");
return DB_E_BADBOOKMARK;
}
// If the contents of our bookmarks are less than 0 or greater than
// rowcount, then they are invalid
UINT nRows = pT->m_rgRowData.GetSize();
if ((*pBookmark <= 0 || *pBookmark > nRows)
&& *pBookmark != DBBMK_FIRST && *pBookmark != DBBMK_LAST)
{
ATLTRACE("Bookmark has invalid range");
return DB_E_BADBOOKMARK;
}
return S_OK;
}
};
У наступного тему ви побачите динамічно визначення стовпців, повернувся до споживача.