IRowsetLocateImpl 구현 완료

구현 완료 하는 IRowsetLocate 인터페이스, 책갈피를 구현 해야 합니다. 책갈피는 행 집합에 고속 데이터 액세스를 허용 하는 인덱스. 책갈피가 고유 수를 결정 하는 공급자가 행을 식별 합니다. 인덱스를 사용 하 여이 예제를 m_rgAgentInfo 배열。

공급자 형식에서 책갈피를 받을 수 있습니다. 책갈피를 유효한 지 확인 하려면:

  1. 유효한 책갈피 포인터를가지고 확인 전화 ValidateBookmark。

  2. DWORD 의 크기 또는 1 바이트 인지 확인 하려면 책갈피의 크기를 확인 합니다. (사용자 레코드 CAgentMan , dwBookmark 항목을 DWORD를 지정 합니다. 싱글 바이트 길이 특별 한 책갈피 DBMRK_FIRST 및 DBMRK_LAST.)

  3. 인덱스 배열 ( 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;
   }
};

다음 항목에서 소비자에 게 반환 되는 열을 동적으로 결정 하는 방법을 볼 수 있습니다.

Index