Terminer la mise en œuvre de IRowsetLocateImpl

Pour compléter votre mise en œuvre de la IRowsetLocate interface, vous devez implémenter des signets. Signets sont des indices dans un ensemble de lignes qui permettent l'accès à haut débit de données. Le fournisseur détermine signets peuvent uniquement identifier une ligne. Cet exemple utilise l'index de la m_rgAgentInfo tableau.

Le fournisseur peut recevoir un signet dans n'importe quel format. Assurez-vous que le signet est valide:

  1. Appelez ValidateBookmark pour vérifier que vous avez un pointeur valide signet.

  2. Vérifiez la taille du signet pour vous assurer que c'est la taille d'un DWORD ou un octet. (L'enregistrement utilisateur, CAgentMan , spécifie l'entrée de dwBookmark pour être un DWORD. La longueur d'octet est utilisée pour les signets spéciales DBMRK_FIRST et DBMRK_LAST).

  3. Vérifier que l'index pointe vers un emplacement valide dans le tableau (entre DBMRK_FIRST et DBMRK_LAST).

Après validation de deux signets (un pour chaque chaîne), appelez la méthode Compare , qui prend deux signets et détermine si l'un est inférieur à, supérieur à, ou égale à l'autre.

Pour extraire les lignes, mettre en œuvre les fonctions GetRowsAt et GetRowsByBookmark.

GetRowsAt fonctionne de la même comme le méthode IRowset::GetNextRows sauf qu'elle utilise un signet pour extraire les données. Il valide le signet, puis appelle IRowsetImpl::GetNextRows pour obtenir les lignes.

GetRowsByBookmark récupère une ligne dans un certain nombre d'endroits. L'utiliser pour extraire des lignes spécifiques. GetRowsByBookmark valide chacun des signets, puis récupère la ligne en appelant IRowsetImpl::CreateRow, qui crée une nouvelle ligne, si nécessaire. Les lignes sont retournées dans le tableau indiqué parrghRows.

(Parce que cet exemple utilise des signets de longueur fixe simples, il n'implémente pas la méthode IRowsetLocate::Hash . Si votre fournisseur utilise des signets de longueur variable ou de signets calculs coûteuses, vous pouvez implémenter la méthode IRowsetLocate::Hash .)

La mise en œuvre complète de IRowsetLocateImpl ressemble à ceci:

/////////////////////////////////////////////////////////////////////////// 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;
   }
};

Dans la rubrique suivante, vous verrez comment déterminer dynamiquement les colonnes retournées au consommateur.

Index