Colunas dinamicamente determinar retornadas para o consumidor

Macros PROVIDER_COLUMN_ENTRY normalmente identificador chamar IColumnsInfo:: GetColumnsInfo . Uma vez que um consumidor pode ou não pode optar por usar marcadores, no entanto, o provedor deve ser capaz de alterar as colunas retornadas dependendo ou não o consumidor pede um indicador.

Para lidar com a chamada de IColumnsInfo:: GetColumnsInfo , excluir the PROVIDER_COLUMN_MAP (que define uma função _GetColumnInfo ) do CAgentMan usuário gravar em MyProviderRS. H e substituí-lo com a definição para o seu próprio _GetColumnInfo função

////////////////////////////////////////////////////////////////////////
/ / MyProviderRS. H
Classe C&AgentMan
{
público:
   DWORD dwBookmark;
   TCHAR szCommand [256];
   TCHAR szText [256];
   TCHAR szCommand2 [256];
   TCHAR szText2 [256];

estático ATLCOLUMNINFO * _GetColumnInfo (void * pThis, ULONG * pcCols);
   bool operador = = (const CAgentManamp; am)
   {
      retornar (lstrcmpi (szCommand, am.szCommand) = = 0);
   }

}

Em seguida, implementar o _GetColumnInfo função em MyProviderRS.cpp, conforme mostrado no código a seguir.

_GetColumnInfoverifica primeiro se a propriedade OOLE DB DBPROP_IRowsetLocate é definida. Para obter a propriedade, _GetColumnInfo usa um ponteiro ( pRowset ) para o objeto de conjunto de linhas. O pThis ponteiro representa a classe que criou o conjunto de linhas (que é a classe onde está armazenado o mapa de propriedade). _GetColumnInfo typecasts a pThis ponteiro para um RMyProviderRowset ponteiro.

Para verificar a propriedade DBPROP_IRowsetLocate , _GetColumnInfo usa a interface de IRowsetInfo , que pode ser obtido por chamado Falha de QueryInterface sobre o pRowset interface. (Como alternativa, você pode usar um ATL CComQIPtr .)

////////////////////////////////////////////////////////////////////
/ / MyProviderRS.cpp
ATLCOLUMNINFO * CAgentMan::_GetColumnInfo(void* pThis, ULONG* pcCols)
{
   estático ATLCOLUMNINFO _rgColumns [5];
   ULONG ulCols = 0;
            
   / / Verificar o sinalizador de propriedade de marcadores, se for definido, defina o zero ordinal
   / / entrada na coluna mapa com as informações de marcador.
   CAgentRowset * pRowset = (CAgentRowset *) pThis;
   CComQIPtrlt; IRowsetInfo, & IID_IRowsetInfo > spRowsetProps = pRowset;

CDBPropIDSet set(DBPROPSET_ROWSET);
   Defina.AddPropertyID(DBPROP_BOOKMARKS);
   DBPROPSET * pPropSet = NULL;
   ULONG ulPropSet = 0;
   HRESULT hr;

se (spRowsetProps)
      hr = spRowsetProps - > GetProperties (1, conjunto, & ulPropSet, & pPropSet);

se (pPropSet)
   {
      CComVariant var = pPropSet - > .vvalue rgProperties [0];
      CoTaskMemFree (pPropSet - > rgProperties);
      CoTaskMemFree(pPropSet);
      
      se (SUCCEEDED(hr) & & (var.boolVal = = VARIANT_TRUE))
      {
         ADD_COLUMN_ENTRY_EX (ulCols, OLESTR("Bookmark"), 0, sizeof(DWORD), DBTYPE_BYTES, 0, 0, GUID_NULL, CAgentMan, dwBookmark, DBCOLUMNFLAGS_ISBOOKMARK)
         ulCols + +;
      }
   }

/ / Em seguida configure as outras colunas.
   ADD_COLUMN_ENTRY (ulCols, OLESTR("Command"), 1, 256, DBTYPE_STR, 0xFF, 0xFF, GUID_NULL, CAgentMan, szCommand)
   ulCols + +;
   ADD_COLUMN_ENTRY (ulCols, OLESTR("Text"), 2, 256, DBTYPE_STR, 0xFF, 0xFF, GUID_NULL, CAgentMan, szText)
   ulCols + +;

ADD_COLUMN_ENTRY (ulCols, OLESTR("Command2"), 3, 256, DBTYPE_STR, 0xFF, 0xFF, GUID_NULL, CAgentMan, szCommand2)
   ulCols + +;
   ADD_COLUMN_ENTRY (ulCols, OLESTR("Text2"), 4, 256, DBTYPE_STR, 0xFF, 0xFF, GUID_NULL, CAgentMan, szText2)
   ulCols + +;

se (pcCols! = NULL)
      * pcCols = ulCols;

retornar _rgColumns;
}

Este exemplo usa uma matriz estática para conter as informações de coluna. Se o consumidor não quer a coluna de indicador, uma entrada na matriz é não utilizada. Para lidar com as informações, você cria duas macros de matriz, ADD_COLUMN_ENTRY e ADD_COLUMN_ENTRY_EX. ADD_COLUMN_ENTRY_EX tem um parâmetro extra, flags , isto é necessário se você designar uma coluna de indicador.

////////////////////////////////////////////////////////////////////////
/ / MyProviderRS. H

# define &ADD_COLUMN_ENTRY (ulCols, nome, ordinal, colSize, tipo, precisão, escala, guid, dataClass, membro) \
   .pwszName _rgColumns [ulCols] = nome (LPOLESTR); \
   .pTypeInfo _rgColumns [ulCols] = (ITypeInfo *) NULL; \
   .iOrdinal _rgColumns [ulCols] = ordinal (ULONG); \
   .dwFlags _rgColumns [ulCols] = 0; \
   _rgColumns [ulCols] .ulcolumnsize = colSize (ULONG); \
   .wType _rgColumns [ulCols] = tipo (DBTYPE); \
   .bPrecision _rgColumns [ulCols] = precisão (BYTE); \
   .bScale _rgColumns [ulCols] = (BYTE) escala; \
   .cbOffset _rgColumns [ulCols] = offsetof (dataClass, membro);

# define ADD_COLUMN_ENTRY_EX (ulCols, nome, ordinal, colSize, tipo, precisão, escala, guid, dataClass, membro, flags) \
   .pwszName _rgColumns [ulCols] = nome (LPOLESTR); \
   .pTypeInfo _rgColumns [ulCols] = (ITypeInfo *) NULL; \
   .iOrdinal _rgColumns [ulCols] = ordinal (ULONG); \
   .dwFlags _rgColumns [ulCols] = sinalizadores; \
   _rgColumns [ulCols] .ulcolumnsize = colSize (ULONG); \
   .wType _rgColumns [ulCols] = tipo (DBTYPE); \
   .bPrecision _rgColumns [ulCols] = precisão (BYTE); \
   .bScale _rgColumns [ulCols] = (BYTE) escala; \
   .cbOffset _rgColumns [ulCols] = offsetof (dataClass, membro); \
   memset(amp;(_rgColumns[ulCols].columnid), 0, sizeof(DBID)); \
   .columnid.uName.pwszName _rgColumns [ulCols] = nome (LPOLESTR)

No _GetColumnInfo função, a macro de indicador é usada como este:

ADD_COLUMN_ENTRY_EX (ulCols, OLESTR("Bookmark"), 0, sizeof(DWORD),
   DBTYPE_BYTES, 0, 0, GUID_NULL, CAgentMan, dwBookmark, DBCOLUMNFLAGS_ISBOOKMARK)

Agora você pode compilar e executar o provedor avançado. Para testar o provedor, modifique o consumidor de teste, conforme descrito em modificar o consumidor para uso com o provedor avançado. Execute teste de consumidor com o provedor. Verifique se que o consumidor teste recupera as seqüências de caracteres apropriadas do provedor ao clicar no botão executar na caixa de diálogo teste consumidor.

Voltar à implementação de um provedor de OOLE DB modelo

Index