Um Ihre Implementierung der abzuschließen die IRowsetLocate -Schnittstelle implementieren, müssen Sie Lesezeichen. Lesezeichen sind Indizes in einem Rowset, die High-Speed-Zugriff auf Daten zu ermöglichen. Der Anbieter bestimmt, was eindeutig Lesezeichen können eine Zeile identifiziert. In diesem Beispiel wird den Index des das m_rgAgentInfo Array.
Der Anbieter kann eine Textmarke in einem beliebigen Format empfangen. Um sicherzustellen, dass das Lesezeichen gültig ist:
CAgentMan , gibt den DwBookmark -Eintrag zu einem DWORD. Die Single-Byte-Länge ist für die speziellen Lesezeichen, DBMRK_FIRST und DBMRK_LASTverwendet.)Rufen Sie nach der Überprüfung von beiden Lesezeichen (eines für jede Zeichenfolge) die Methode vergleichen , die zwei Lesezeichen und bestimmt, ob eine kleiner, größer ist, oder gleich auf die andere.
Um Zeilen abzurufen, implementieren Sie die GetRowsAt und GetRowsByBookmark Funktionen.
GetRowsAt funktioniert genauso wie die IRowset:: GetNextRows -Methode mit der Ausnahme, dass ein Lesezeichen verwendet um die Daten abzurufen. Es überprüft das Lesezeichen und ruft dann IRowsetImpl::GetNextRows auf die Zeilen zu erhalten.
GetRowsByBookmark holt eine Zeile an mehreren Standorten. Verwenden Sie, um bestimmte Zeilen abzurufen. GetRowsByBookmark überprüft jedes der Lesezeichen, dann holt die Zeile durch Aufrufen IRowsetImpl::CreateRow, erzeugt eine neue Zeile, wenn nötig. Die Zeilen werden in das Array auf verweist zurückgegeben.rghRows.
(Da in diesem Beispiel einfache fester Länge Lesezeichen verwendet, wird es nicht die IRowsetLocate::Hash -Methode implementiert. Wenn Ihr Provider variabler Länge Lesezeichen oder rechnerisch teuer Lesezeichen verwendet, können Sie die IRowsetLocate::Hash -Methode implementieren.)
Die vollständige Implementierung von IRowsetLocateImpl sieht so aus:
/////////////////////////////////////////////////////////////////////////// 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;
}
};
Im nächsten Thema sehen Sie Gewusst wie: Dynamisches Festlegen die an den Consumer zurückgegebenen Spalten.