Suporte a conjuntos de linhas do esquema
Conjuntos de linhas do esquema permitem que os consumidores obter informações sobre o armazenamento de dados sem conhecer a sua estrutura subjacente, ou esquema. Por exemplo, um armazenamento de dados pode ter tabelas organizadas em uma hierarquia definida pelo usuário, portanto, não haveria nenhuma maneira de garantir que o conhecimento do esquema, exceto por leitura. (Como outro exemplo, observe que os assistentes do Visual C++ usam conjuntos de linhas do esquema para gerar acessadores para o consumidor). Para permitir que o consumidor fazer isso, o objeto de sessão do provedor expõe métodos sobre o IDBSchemaRowset interface. Em aplicativos do Visual C++, você usar o IDBSchemaRowsetImpl classe para implementar IDBSchemaRowset.
IDBSchemaRowsetImplsuporta os seguintes métodos:
CheckRestrictions verifica a validade das restrições de um conjunto de linhas do esquema.
CreateSchemaRowset implementa uma função de criador do objeto COM para o objeto especificado pelo parâmetro de modelo.
SetRestrictions Especifica quais restrições de suporte em um conjunto de linhas do esquema específico.
IDBSchemaRowset::GetRowset retorna um conjunto de linhas do esquema (herdado da interface).
GetSchemas retorna uma lista de conjuntos de linhas do esquema pode ser acessado pelo IDBSchemaRowsetImpl::GetRowset (herdado da interface).
Suporte para o assistente ATL OLE DB Provider
ATL OLE DB Provider Wizard cria três classes de esquema no arquivo de cabeçalho de sessão:
CShortNameSessionTRSchemaRowset
CShortNameSessionColSchemaRowset
CShortNameSessionPTSchemaRowset
Essas classes são responder às solicitações do consumidor de informações de esquema; Observe que a especificação OLE DB exige o suporte desses conjuntos de linhas do esquema de três:
CShortNameSessionTRSchemaRowset lida com solicitações de informações da tabela (o DBSCHEMA_TABLES conjunto de linhas de esquema).
CShortNameSessionColSchemaRowset lida com solicitações de informações de coluna (o DBSCHEMA_COLUMNS conjunto de linhas de esquema). O assistente fornece exemplos de implementações para essas classes, retornam informações de esquema para um provedor DOS.
CShortNameSessionPTSchemaRowset lida com solicitações de informações de esquema sobre o tipo de provedor (o DBSCHEMA_PROVIDER_TYPES conjunto de linhas de esquema). A implementação padrão fornecida pelo assistente retorna S_OK.
Você pode personalizar essas classes para lidar com informações de esquema apropriadas ao seu provedor:
Em cShortNameSessionTRSchemaRowset, você deve preencher os campos de catálogo, tabela e descrição (trData.m_szType, trData.m_szTable, e trData.m_szDesc). O exemplo gerado pelo assistente usa apenas uma linha (tabela). Outros provedores podem retornar mais de uma tabela.
Em cShortNameSessionColSchemaRowset, passe o nome da tabela como um DBID.
Restrições de configuração
Um conceito importante no suporte do conjunto de linhas de esquema é definir as restrições, usando SetRestrictions. Restrições permitem que os consumidores buscar somente as linhas correspondentes (por exemplo, localizar todas as colunas na tabela "MinhaTabela"). As restrições são opcionais e, no caso em que nenhum são suportados (padrão), todos os dados sempre será retornado. Para obter um exemplo de um provedor que oferece suporte a restrições, consulte o UpdatePV exemplo.
Configurando o mapa de esquema
Configure um mapa de esquema como no Session.h em UpdatePV:
BEGIN_SCHEMA_MAP(CUpdateSession)
SCHEMA_ENTRY(DBSCHEMA_TABLES, CUpdateSessionTRSchemaRowset)
SCHEMA_ENTRY(DBSCHEMA_COLUMNS, CUpdateSessionColSchemaRowset)
SCHEMA_ENTRY(DBSCHEMA_PROVIDER_TYPES, CUpdateSessionPTSchemaRowset)
END_SCHEMA_MAP()
Para oferecer suporte a IDBSchemaRowset, você deve oferecer suporte a DBSCHEMA_TABLES, DBSCHEMA_COLUMNS, e DBSCHEMA_PROVIDER_TYPES. Você pode adicionar conjuntos de linhas do esquema adicionais a seu critério.
Declare uma classe de conjunto de linhas de esquema com um Execute método como CUpdateSessionTRSchemaRowset em UpdatePV:
class CUpdateSessionTRSchemaRowset :
public CSchemaRowsetImpl < CUpdateSessionTRSchemaRowset,
CTABLESRow, CUpdateSession >
...
// Execute looks like this; what pointers does the consumer use?
HRESULT Execute(DBROWCOUNT* pcRowsAffected,
ULONG cRestrictions, const VARIANT* rgRestrictions)
Observe que CUpdateSession herda de IDBSchemaRowsetImpl, portanto, ele tem todos os a restrição de manipulação de métodos. Usando CSchemaRowsetImpl, declarar a três classes de filho (listados no mapa de esquema acima): CUpdateSessionTRSchemaRowset, CUpdateSessionColSchemaRowset, and CUpdateSessionPTSchemaRowset. Cada uma dessas classes filho tem um Execute método que manipula o seu respectivo conjunto de restrições (critérios de pesquisa). Cada Execute método compara os valores da cRestrictions e rgRestrictions parâmetros. Consulte a descrição desses parâmetros no SetRestrictions.
Para obter mais informações sobre quais restrições correspondem a um conjunto de linhas do esquema específico, consulte a tabela do conjunto de linhas do esquema GUIDs em IDBSchemaRowset na OLE DB Programmer referência na Windows SDK.
Por exemplo, se você tem o suporte a TABLE_NAME restrição DBSCHEMA_TABLES, você deve fazer o seguinte:
Pesquisar primeiro, DBSCHEMA_TABLES e veja o que ele oferece suporte a quatro restrições (em ordem).
Restrição de conjunto de linhas do esquema |
Valor de restrição |
---|---|
TABLE_CATALOG |
0x1 (1 binário) |
TABLE_SCHEMA |
0x2 (binário 10) |
TABLE_NAME |
0x4 (100 em binário) |
TABLE_TYPE |
0x8 (1000 binário) |
Em seguida, observe que há um bit de cada restrição. Porque você deseja oferecer suporte a TABLE_NAME somente, retornaria 0x4 na rgRestrictions elemento. Se você tem o suporte TABLE_CATALOG e TABLE_NAME, retornaria o 0x5 (101 binário).
Por padrão, a implementação retorna 0 (não oferece suporte a quaisquer restrições) para qualquer solicitação. UpdatePV é um exemplo de um provedor que oferece suporte a restrições.
Example
Esse código é retirado da UpdatePV exemplo. UpdatePv suporta os três conjuntos de linhas do esquema necessário: DBSCHEMA_TABLES, DBSCHEMA_COLUMNS, e DBSCHEMA_PROVIDER_TYPES. Como um exemplo de como implementar o suporte ao esquema no seu provedor, este tópico leva você através de implementação de DBSCHEMA_TABLE conjunto de linhas.
Observação |
---|
O código de exemplo pode diferir do que está listado aqui. Você deve considerar o código de exemplo de como a versão mais atualizada. |
Adicionando suporte a esquema a primeira etapa é determinar quais restrições que você pretende dar suporte. Para determinar quais restrições estão disponíveis para o conjunto de linhas do esquema, examine a especificação OLE DB para a definição de IDBSchemaRowset. Após a definição do principal, você verá uma tabela contendo o nome do conjunto de linhas de esquema, o número de restrições e as colunas de restrição. Selecione o conjunto de linhas de esquema que você deseja oferecer suporte e anote o número de colunas de restrição e restrições. Por exemplo, DBSCHEMA_TABLES aceita quatro restrições (TABLE_CATALOG, TABLE_SCHEMA, TABLE_NAME, e TABLE_TYPE):
void SetRestrictions(ULONG cRestrictions, GUID* rguidSchema,
ULONG* rgRestrictions)
{
for (ULONG l=0; l<cRestrictions; l++)
{
if (InlineIsEqualGUID(rguidSchema[l], DBSCHEMA_TABLES))
rgRestrictions[l] = 0x0C;
else if (InlineIsEqualGUID(rguidSchema[l], DBSCHEMA_COLUMNS))
rgRestrictions[l] = 0x04;
else if (InlineIsEqualGUID(rguidSchema[l],
DBSCHEMA_PROVIDER_TYPES))
rgRestrictions[l] = 0x00;
}
}
Um bit representa cada coluna de restrição. Se você deseja oferecer suporte a uma restrição (isto é, você pode consultar por ele), defina esse bit para 1. Se não desejar oferecer suporte a uma restrição, defina esse bit para zero. A partir da linha de código acima, oferece suporte a UpdatePV a TABLE_NAME e TABLE_TYPE restrições sobre o DBSCHEMA_TABLES conjunto de linhas. Essas são as restrições de (máscara de bits 1000) quarta e o terceiro (máscara de bits 100). Portanto, a máscara de bits para UpdatePv é 1100 (ou 0x0C):
if (InlineIsEqualGUID(rguidSchema[l], DBSCHEMA_TABLES))
rgRestrictions[l] = 0x0C;
O seguinte Execute função é semelhante aos conjuntos de linhas regulares. Você tem três argumentos: pcRowsAffected, cRestrictions, and rgRestrictions. O pcRowsAffected variável é um parâmetro de saída que o provedor pode retornar a contagem de linhas no conjunto de linhas de esquema. O cRestrictions parâmetro é um parâmetro de entrada que contém o número de restrições que passaram pelo consumidor do provedor. O rgRestrictions parâmetro é uma matriz de VARIANT os valores que contêm os valores de restrição.
HRESULT Execute(DBROWCOUNT* pcRowsAffected, ULONG cRestrictions,
const VARIANT* rgRestrictions)
O cRestrictions variável baseia-se o número total de restrições para um conjunto de linhas do esquema, independentemente se o provedor de suporte. Como UpdatePv oferece suporte a duas restrições (a terceira e quarta), esse código somente procura por um cRestrictions valor maior ou igual a 3.
O valor para o TABLE_NAME restrição é armazenada em rgRestrictions[2] (novamente, a terceira restrição em uma matriz baseada em zero é 2). Você precisa verificar a restrição não é VT_EMPTY para suporte, na verdade, o proprietário. Observe que VT_NULL não é igual a VT_EMPTY. VT_NULL Especifica um valor válido de restrição.
A definição de UpdatePv de um nome de tabela é um nome de caminho totalmente qualificado para um arquivo de texto. Extrair o valor de restrição e tentar abrir o arquivo para garantir que o arquivo existe de fato. Se o arquivo não existir, retornar S_OK. Isso pode parecer um pouco para trás, mas o código que realmente está informando o consumidor é que não havia nenhuma tabela suportada pelo nome especificado. O S_OK retorno significa que o código seja executado corretamente.
USES_CONVERSION;
enum {
sizeOfszFile = 255
};
CTABLESRow trData;
FILE *pFile = NULL;
TCHAR szFile[ sizeOfszFile ];
errcode err = 0;
// Handle any restrictions sent to us. This only handles
// the TABLE_NAME & TABLE_TYPE restictions (the 3rd and 4th
// restrictions in DBSCHEMA_TABLES...look in IDBSchemaRowsets
// in part 2 of the prog. ref) so your restrictions are 0x08 & 0x04
// for a total of (0x0C)
if (cRestrictions >= 3 && rgRestrictions[2].vt != VT_EMPTY)
{
CComBSTR bstrName = rgRestrictions[2].bstrVal;
if ((rgRestrictions[2].vt == VT_BSTR) && (bstrName != (BSTR)NULL))
{
// Check to see if the file exists
_tcscpy_s(&szFile[0], sizeOfszFile, OLE2T(bstrName));
if (szFile[0] == _T('\0') ||
((err = _tfopen(&pFile, &szFile[0], _T("r"))) == 0))
{
return S_OK;// Their restriction was invalid return no data
}
else
{
fclose(pFile);
}
}
}
Suporte a restrição de quarta (TABLE_TYPE) é semelhante à restrição de terceira. Verifique o valor não é VT_EMPTY. Essa restrição só retorna o tipo de tabela, tabela. Para determinar os valores válidos para o DBSCHEMA_TABLES, procure no Apêndice B da OLE DB Programmer referência na tabelas seção do conjunto de linhas.
// TABLE_TYPE restriction:
if (cRestrictions >=4 && rgRestrictions[3].vt != VT_EMPTY)
{
CComBSTR bstrType = rgRestrictions[3].bstrVal;
if ((rgRestrictions[3].vt == VT_BSTR) && (bstrType != (BSTR)NULL))
{
// This is kind of a blind restriction.
// This only actually supports
// TABLES so if you get anything else,
// just return an empty rowset.
if (_tcscmp(_T("TABLE"), OLE2T(bstrType)) != 0)
return S_OK;
}
}
Isso é onde você realmente cria uma entrada de linha para o conjunto de linhas. A variável trData corresponde a CTABLESRow, uma estrutura definida nos modelos de provedor OLE DB. CTABLESRow corresponde do tabelas a definição de conjunto de linhas no Apêndice B da especificação do OLE DB. Você só tem uma linha para adicionar porque você só pode suportar uma tabela por vez.
// Bring over the data:
wcspy_s(trData.m_szType, OLESTR("TABLE"), 5);
wcspy_s(trData.m_szDesc, OLESTR("The Directory Table"), 19);
wcsncpy_s(trData.m_szTable, T2OLE(szFile), _TRUNCATE());
UpdatePV define apenas três colunas: Table_name, TABLE_TYPE, e Descrição. Você deve anotar as colunas que você retornar informações, porque você precisará dessas informações quando você implementa GetDBStatus:
_ATLTRY
{
m_rgRowData.Add(trData);
}
_ATLCATCHALL()
{
return E_OUTOFMEMORY;
}
//if (!m_rgRowData.Add(trData))
// return E_OUTOFMEMORY;
*pcRowsAffected = 1;
return S_OK;
}
O GetDBStatus função é muito importante para o funcionamento correto do conjunto de linhas do esquema. Porque você não retornar os dados para cada coluna na tabelas conjunto de linhas, você precisa especificar quais colunas você retorna dados para e que você não fizer isso.
virtual DBSTATUS GetDBStatus(CSimpleRow* , ATLCOLUMNINFO* pColInfo)
{
ATLASSERT(pColInfo != NULL);
switch(pColInfo->iOrdinal)
{
case 3: // TABLE_NAME
case 4: // TABLE_TYPE
case 6: // DESCRIPTION
return DBSTATUS_S_OK;
break;
default:
return DBSTATUS_S_ISNULL;
break;
}
}
Porque seu Execute função retorna os dados para o TABLE_NAME, TABLE_TYPE, e Descrição os campos de tabelas o conjunto de linhas, você pode procurar no Apêndice B da especificação do OLE DB e determinar (contando da parte superior para baixo) que são números ordinais, 3, 4 e 6. Para cada uma das colunas, retornar DBSTATUS_S_OK. Para todas as outras colunas, retornar DBSTATUS_S_ISNULL. É importante retornar esse status porque um consumidor pode não entender o valor que você retornar é Nulo ou algo mais. Observe que, novamente, Nulo não é equivalente ao vazio.
Para obter mais informações sobre a interface de conjunto de linhas do esquema do OLE DB, consulte o IDBSchemaRowset interface de referência do OLE DB do programador.
Para obter informações sobre como usar os consumidores IDBSchemaRowset métodos, consulte Obter metadados com conjuntos de linhas do esquema.
Para obter um exemplo de um provedor que ofereça suporte a conjuntos de linhas do esquema, consulte o UpdatePV exemplo.