Share via


Implementar un consumidor sencillo

Actualización: noviembre 2007

En los siguientes temas se muestra cómo modificar los archivos que crea el Asistente para aplicaciones MFC y el Asistente para consumidores OLE DB ATL para crear un consumidor sencillo. Este ejemplo se divide en las siguientes partes:

  • En "Recuperar datos con el consumidor" se muestra cómo implementar en el consumidor código que lee todos los datos, fila por fila, de una tabla de base de datos.

  • En "Agregar compatibilidad con marcadores al consumidor" se muestra cómo agregar compatibilidad con marcadores al consumidor.

  • En "Agregar compatibilidad con XML al consumidor" se muestra cómo modificar el código del consumidor para producir como resultado los datos del conjunto de filas recuperadas como datos XML.

Nota:

Puede utilizar la aplicación de consumidor que se describe en esta sección para probar los proveedores de ejemplo MyProv y Provider.

Nota:

Si desea crear una aplicación de consumidor para probar MyProv (el proveedor que se describe en Mejorar un proveedor sencillo de sólo lectura), debe incluir la compatibilidad con marcadores como se describe en "Agregar compatibilidad con marcadores al consumidor".

Nota:

Si desea crear una aplicación de consumidor para probar Provider, omita la parte relativa a la compatibilidad con marcadores que se describe en "Agregar compatibilidad con marcadores al consumidor" y pase a "Agregar compatibilidad con XML al consumidor".

Recuperar datos con el consumidor

Para modificar la aplicación de consola de forma que utilice el consumidor OLE DB

  • En MyCons.cpp, cambie el código principal mediante la inserción del texto que aparece en negrita a continuación:

    // MyCons.cpp : Defines the entry point for the console application.
    //
    #include "stdafx.h"
    #include "Products.h"
    ...
    int main(int argc, char* argv[])
    {
       HRESULT hr = CoInitialize(NULL);   // Instantiate rowset   CProducts rs;   hr = rs.OpenAll();   ATLASSERT( SUCCEEDED( hr ) );   hr = rs.MoveFirst();   // Iterate through the rowset   while( SUCCEEDED(hr) && hr != DB_S_ENDOFROWSET )   {      // Print out the column information for each row      printf("Product ID: %d, Name: %s, Unit Price: %d, Quantity per Unit: %d, Units in Stock %d, Reorder Level %d\n",             rs.m_ProductID, rs.m_ProductName, rs.m_UnitPrice, rs.m_QuantityPerUnit, rs.m_UnitsInStock, rs.m_ReorderLevel );      hr = rs.MoveNext();   }   rs.Close();   rs.ReleaseCommand();   CoUninitialize();
    
       return 0;
    }
    

Agregar compatibilidad con marcadores al consumidor

Un marcador es una columna que identifica de manera única filas de la tabla. Normalmente es la columna clave, pero no siempre: es específico de cada proveedor. En esta sección se muestra cómo agregar compatibilidad con marcadores. Para ello, debe llevar a cabo los pasos siguientes en la clase de registro de usuario:

  • Cree instancias de los marcadores. Éstos son objetos de tipo CBookmark.

  • Solicite una columna de marcador del proveedor estableciendo la propiedad DBPROP_IRowsetLocate.

  • Agregue una entrada de marcador al mapa de columnas mediante la macro BOOKMARK_ENTRY.

Con los pasos anteriores se genera compatibilidad con marcadores y un objeto de marcador con el que trabajar. Con este código de ejemplo, el marcador se muestra de la siguiente manera:

  • Se abre un archivo para escritura.

  • Se envían los datos del conjunto de filas al archivo, fila por fila.

  • Se llama a MoveToBookmark para mover el cursor del conjunto de filas al marcador.

  • Se envía la fila marcada, anexándola al final del archivo.

Nota:

Si utiliza esta aplicación de consumidor para probar la aplicación de proveedor de ejemplo Provider, omita la parte relativa a la compatibilidad con marcadores que se describe en esta sección.

Para crear una instancia del marcador

  • El descriptor de acceso tiene que contener un objeto de tipo CBookmark. Con el parámetro nSize se especifica el tamaño del búfer del marcador en bytes (normalmente 4 en las plataformas de 32 bits y 8 en las de 64 bits). Agregue la siguiente declaración a los miembros de datos de columna de la clase de registro de usuario:

    //////////////////////////////////////////////////////////////////////
    // Products.h
    class CProductsAccessor
    {
    public:
       CBookmark<4> m_bookmark;   // Add bookmark declaration
       LONG m_ProductID;
       ...
    

Para solicitar una columna de marcador al proveedor

  • Agregue el siguiente código al método GetRowsetProperties de la clase de registro de usuario:

    // Set the DBPROP_IRowsetLocate property.
    void GetRowsetProperties(CDBPropSet* pPropSet)
    {
       pPropSet->AddProperty(DBPROP_CANFETCHBACKWARDS, true, DBPROPOPTIONS_OPTIONAL);
       pPropSet->AddProperty(DBPROP_CANSCROLLBACKWARDS, true, DBPROPOPTIONS_OPTIONAL);
       // Add DBPROP_IRowsetLocate property to support bookmarks   pPropSet->AddProperty(DBPROP_IRowsetLocate, true);
    }
    

Para agregar una entrada de marcador al mapa de columnas

  • Agregue la siguiente entrada al mapa de columnas de la clase de registro de usuario:

    // Set a bookmark entry in the column map.
    BEGIN_COLUMN_MAP(CProductsAccessor)
       BOOKMARK_ENTRY(m_bookmark)   // Add bookmark entry
       COLUMN_ENTRY_LENGTH_STATUS(1, m_ProductID, m_dwProductIDLength, m_dwProductIDStatus)
       COLUMN_ENTRY_LENGTH_STATUS(2, m_ProductName, m_dwProductNameLength, m_dwProductNameStatus)
    ...
    END_COLUMN_MAP()
    

Para utilizar un marcador en el código principal

  • En el archivo MyCons.cpp de la aplicación de consola que creó anteriormente, cambie el código principal para que se lea como sigue: Para utilizar marcadores, el código principal tiene que crear instancias de su propio objeto de marcador (myBookmark); se trata de un marcador distinto al del descriptor de acceso (m_bookmark).

    ///////////////////////////////////////////////////////////////////////
    // MyCons.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include "Products.h" 
    #include <iostream>
    #include <fstream>
    using namespace std;
    
    int _tmain(int argc, _TCHAR* argv[])
    {
       HRESULT hr = CoInitialize(NULL);
    
       // Instantiate rowset
       CProducts rs;
    
       hr = rs.OpenAll();
       hr = rs.MoveFirst();
    
       // Cast CURRENCY m_UnitPrice to a long value
       LONGLONG lPrice = rs.m_UnitPrice.int64;
    
       // Open file output.txt for writing in overwrite mode
       ofstream outfile( "C:\\output.txt", ios::out );
    
       if (!outfile)      // Test for invalid file
          return -1;
    
       // Instantiate a bookmark object myBookmark for the main code
       CBookmark<4> myBookmark;
       int nCounter = 0;
    
       // Iterate through the rowset and output column data to output.txt row by row
       // In the file, mark the beginning of this set of data:
       outfile << "initial row dump" << endl;
       while( SUCCEEDED(hr) && hr != DB_S_ENDOFROWSET )
       {
          nCounter++;
          if( nCounter == 5 )
             myBookmark = rs.bookmark;
          // Output the column information for each row:
          outfile << rs.m_ProductID << rs.m_ProductName << lPrice << rs.m_QuantityPerUnit << rs.m_UnitsInStock << rs.m_ReorderLevel << endl;
          hr = rs.MoveNext();
       }
    
       // Move cursor to bookmark
       hr = rs.MoveToBookmark(myBookmark);
    
       // Iterate through the rowset and output column data to output.txt row by row
       // In the file, mark the beginning of this set of data:
       outfile << "row dump starting from bookmarked row" << endl;
       while( SUCCEEDED(hr) && hr != DB_S_ENDOFROWSET )
       {
          // Output the column information for each row
          outfile << rs.m_ProductID << rs.m_ProductName << lPrice << rs.m_QuantityPerUnit << rs.m_UnitsInStock << rs.m_ReorderLevel << endl;
          hr = rs.MoveNext();
       }
    
       rs.CloseAll();
       CoUninitialize();
    
       return 0;
    }
    

Para obtener más información acerca de los marcadores, vea Utilizar marcadores. Además, en Actualizar conjuntos de filas se muestran varios ejemplos de marcadores.

Agregar compatibilidad con XML al consumidor

Como se describe en Obtener acceso a datos XML, existen dos maneras de recuperar datos XML en un origen de datos: mediante CStreamRowset o mediante CXMLAccessor. En este ejemplo se utiliza CStreamRowset, que es más eficaz, pero requiere que SQL Server 2000 se ejecute en el equipo en el que se ejecuta esta aplicación de ejemplo.

Para modificar la clase de comando de forma que herede de CStreamRowset

  • En la aplicación de consumidor que se creó anteriormente, cambie la declaración CCommand de la forma siguiente para especificar CStreamRowset como clase de conjunto de filas:

    class CProducts : public CCommand<CAccessor<CProductsAccessor>, CStreamRowset >
    

Para modificar el código principal de forma que recupere y produzca como resultado los datos XML

  • En el archivo MyCons.cpp de la aplicación de consola que creó anteriormente, cambie el código principal para que se lea como sigue:

    ///////////////////////////////////////////////////////////////////////
    // MyCons.cpp : Defines the entry point for the console application.
    //
    
    #include "stdafx.h"
    #include "Products.h" 
    #include <iostream>
    #include <fstream>
    using namespace std;
    
    int _tmain(int argc, _TCHAR* argv[])
    {
       HRESULT hr = CoInitialize(NULL);
    
       // Instantiate rowset
       CProducts rs;
    
       // Add variable declarations for the Read method to handle sequential stream data
       CHAR buffer[1001];  // Pointer to buffer into which data stream is read
       ULONG cbRead;       // Actual number of bytes read from the data stream
    
       hr = rs.OpenAll();
    
       // Open file output.txt for writing in overwrite mode
       ofstream outfile( "C:\\output.txt", ios::out );
    
       if (!outfile)      // Test for invalid file
          return -1;
    
       // The following loop reads 1000 bytes of the data stream at a time 
       // until it reaches the end of the data stream
       for (;;)
       {
          // Read sequential stream data into buffer
          HRESULT hr = rs.m_spStream->Read(buffer, 1000, &cbRead);
          if (FAILED (hr))
             break;
          // Output buffer to file
          buffer[cbRead] = 0;
          outfile << buffer;
          // Test for end of data stream
          if (cbRead < 1000)
             break;
       }
    
       rs.CloseAll();
       CoUninitialize();
    
       return 0;
    }
    

Vea también

Conceptos

Crear un consumidor OLE DB mediante un asistente