Verwirklichung des IRowsetLocateImpl

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:

  1. Rufen Sie ValidateBookmark , überprüfen, ob Sie einen gültiges Lesezeichen-Zeiger.

  2. Überprüfen Sie die Größe des Lesezeichens um sicherzustellen, dass sie entweder die Größe des ein DWORD oder ein Byte ist. (Den Benutzerdatensatz, CAgentMan , gibt den DwBookmark -Eintrag zu einem DWORD. Die Single-Byte-Länge ist für die speziellen Lesezeichen, DBMRK_FIRST und DBMRK_LASTverwendet.)

  3. Überprüfen Sie, ob der Index auf einen gültigen Speicherort im Array (zwischen DBMRK_FIRST und DBMRK_LAST verweist).

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.

Index