Classe CRowset
Encapsula um objeto de conjunto de linhas OLE DB e várias interfaces relacionadas e fornece métodos de manipulação para dados de conjunto de linhas.
Sintaxe
template <class TAccessor = CAccessorBase>
class CRowset
Parâmetros
TAccessor
Uma classe de acessador. O padrão é CAccessorBase
.
Requisitos
Cabeçalho: atldbcli.h
Membros
Métodos
Nome | Descrição |
---|---|
AddRefRows | Incrementa a contagem de referência associada à linha atual. |
Fechar | Libera linhas e a interface atual de IRowset . |
Comparar | Compara dois indicadores usando IRowsetLocate::Compare. |
CRowset | Cria um novo objeto CRowset e (opcionalmente) o associa a uma interface IRowset , fornecida como um parâmetro. |
Delete (excluir) | Exclui linhas do conjunto de linhas usando IRowsetChange:DeleteRows. |
FindNextRow | Localiza a próxima linha correspondente após o indicador especificado. |
GetApproximatePosition | Retorna a posição aproximada de uma linha correspondente a um indicador. |
GetData | Recupera dados da cópia do conjunto de linhas da linha. |
GetDataHere | Recupera dados do buffer especificado. |
GetOriginalData | Recupera os dados do fetch mais recente obtidos ou transmitidos para a fonte de dados, ignorando as alterações pendentes. |
GetRowStatus | Retorna o status de todas as linhas. |
Inserção | Cria e insere uma nova linha usando IRowsetChange:InsertRow. |
IsSameRow | Compara a linha especificada com a linha atual. |
MoveFirst | Reposiciona o local de fetch seguinte para a posição inicial. |
MoveLast | Move para o último registro. |
MoveNext | Efetua fetch dos dados da próxima linha sequencial ou um número especificado de posições além da próxima linha. |
MovePrev | Move para o registro anterior. |
MoveToBookmark | Efetua fetch da linha marcada por um indicador ou a linha em um deslocamento especificado desse indicador. |
MoveToRatio | Efetua fetch das linhas iniciando de uma posição fracionária no conjunto de linhas. |
ReleaseRows | Chama IRowset::ReleaseRows para liberar o identificador de linha atual. |
SetData | Define valores de dados em uma ou mais colunas de uma linha usando IRowsetChange:SetData. |
Desfazer | Desfaz todas as alterações feitas em uma linha desde o último fetch ou atualização. |
Atualizar | Transmite todas as alterações pendentes feitas na linha atual desde o último fetch ou atualização. |
UpdateAll | Transmite todas as alterações pendentes feitas em todas as linhas desde o último fetch ou atualização. |
Comentários
No OLE DB, um conjunto de linhas é o objeto por meio do qual um programa define e recupera dados.
Essa classe não se destina a ser instanciada, mas sim passada como um parâmetro de modelo para CTable
ou CCommand
(CRowset
é o padrão).
CRowset::AddRefRows
Chama IRowset::AddRefRows para incrementar (por um) a contagem de referência associada ao identificador de linha atual.
Sintaxe
HRESULT AddRefRows() throw();
Valor retornado
Um valor HRESULT padrão.
Comentários
Esse método incrementa a contagem de referência para o identificador de linha atual. Chame ReleaseRows para decrementar a contagem. As linhas retornadas pelos métodos de movimentação têm uma contagem de referência de um.
CRowset::Close
Libera linhas e a interface IRowset atual.
Sintaxe
void Close() throw();
Comentários
Esse método libera todas as linhas atualmente no conjunto de linhas.
CRowset::Compare
Compara dois indicadores usando IRowsetLocate::Compare.
Sintaxe
HRESULT Compare(const CBookmarkBase& bookmark1,
const CBookmarkBase& bookmark2,
DBCOMPARE* pComparison) const throw();
Parâmetros
Bookmark1
[in] O primeiro indicador a ser comparado.
Bookmark2
[in] O segundo indicador a ser comparado.
pComparison
[out] Um ponteiro para o resultado da comparação.
Valor de retorno
Um valor HRESULT padrão.
Comentários
Esse método requer a interface IRowsetLocate
, opcional, que pode não ter suporte em todos os provedores; se esse for o caso, o método retornará E_NOINTERFACE. Você também deve definir DBPROP_IRowsetLocate
como VARIANT_TRUE antes de chamar Open
sobre a tabela ou o comando que contém o conjunto de linhas.
Para obter informações sobre como usar indicadores em consumidores, consulte Usando indicadores.
CRowset::CRowset
Cria um novo objeto CRowset
e (opcionalmente) o associa a uma interface IRowset, fornecida como um parâmetro.
Sintaxe
CRowset();
CRowset(IRowset* pRowset);
Parâmetros
pRowset
[in] Um ponteiro para uma interface IRowset
a ser associada a essa classe.
CRowset::Delete
Chama IRowsetChange::DeleteRows para excluir a linha atual do conjunto de linhas.
Sintaxe
HRESULT Delete() const throw();
Valor retornado
Um valor HRESULT padrão.
CRowset::FindNextRow
Localiza a próxima linha correspondente após o indicador especificado.
Sintaxe
HRESULT FindNextRow(DBCOMPAREOP op,
BYTE* pData,
DBTYPE wType,
DBLENGTH nLength,
BYTE bPrecision,
BYTE bScale,
BOOL bSkipCurrent = TRUE,
CBookmarkBase* pBookmark = NULL) throw();
Parâmetros
op
[in] A operação a ser usada na comparação de valores de linha. Para obter valores, consulte IRowsetFind::FindNextRow.
pData
[in] Um ponteiro para o valor a ser correspondido.
wType
[in] Indica o tipo de dados da parte de valor do buffer. Para obter informações sobre indicadores de tipo, consulte Tipos de Dados na Referência do Programador OLE DB no SDK do Windows.
nLength
[in] O comprimento, em bytes, da estrutura de dados do consumidor alocada para o valor de dados. Para obter detalhes, consulte a descrição de cbMaxLen
em Estruturas DBBINDING na Referência do programador OLE DB.
bPrecision
[in] A precisão máxima usada ao obter dados. Usado somente se wType for DBTYPE_NUMERIC. Para obter mais informações, consulte Conversões envolvendo DBTYPE_NUMERIC ou DBTYPE_DECIMAL na Referência do Programador OLE DB.
bScale
[in] A escala usada ao obter dados. Usado somente se wType for DBTYPE_NUMERIC ou DBTYPE_DECIMAL. Para obter mais informações, consulte Conversões envolvendo DBTYPE_NUMERIC ou DBTYPE_DECIMAL na Referência do Programador OLE DB.
bSkipCurrent
[in] O número de linhas do indicador no qual iniciar uma pesquisa.
pBookmark
[in] O indicador para a posição na qual iniciar uma pesquisa.
Valor de retorno
Um valor HRESULT padrão.
Comentários
Esse método requer a interface IRowsetFind
, opcional, que pode não ter suporte em todos os provedores; se esse for o caso, o método retornará E_NOINTERFACE. Você também deve definir DBPROP_IRowsetFind
como VARIANT_TRUE antes de chamar Open
sobre a tabela ou o comando que contém o conjunto de linhas.
Para obter informações sobre como usar indicadores em consumidores, consulte Usando indicadores.
CRowset::GetApproximatePosition
Retorna a posição aproximada de uma linha correspondente a um indicador.
Sintaxe
HRESULT GetApproximatePosition(const CBookmarkBase* pBookmark,
DBCOUNTITEM* pPosition,
DBCOUNTITEM* pcRows) throw();
Parâmetros
pBookmark
[in] Um ponteiro para um indicador que identifica a linha cuja posição deve ser encontrada. NULL se apenas a contagem de linhas for necessária.
pPosition
[out] Um ponteiro para o local onde GetApproximatePosition
retornará a posição da linha. NULL se a posição não for necessária.
pcRows
[out] Um ponteiro para o local onde GetApproximatePosition
retornará o número total de linhas. NULL se a contagem de linhas não for necessária.
Valor de retorno
Um valor HRESULT padrão.
Comentários
Esse método requer a interface IRowsetScroll
, opcional, que pode não ter suporte em todos os provedores; se esse for o caso, o método retornará E_NOINTERFACE. Você também deve definir DBPROP_IRowsetScroll
como VARIANT_TRUE antes de chamar Open
sobre a tabela ou o comando que contém o conjunto de linhas.
Para obter informações sobre como usar indicadores em consumidores, consulte Usando indicadores.
CRowset::GetData
Recupera dados da cópia do conjunto de linhas da linha.
Sintaxe
HRESULT GetData() throw();
HRESULT GetData(int nAccessor) throw();
Parâmetros
nAccessor
[in] O número de índice (deslocamento zero) do acessador a ser usado para acessar os dados.
Valor de retorno
Um valor HRESULT padrão.
Comentários
Se você especificar um acessador que não seja um autoaccessor em BEGIN_ACCESSOR, use esse método para obter explicitamente os dados passando o número do acessador.
CRowset::GetDataHere
Recupera dados da linha atual e os coloca no buffer especificado.
Sintaxe
HRESULT GetDataHere(int nAccessor,
void* pBuffer) throw();
Parâmetros
nAccessor
[in] O número de índice do acessador a ser usado para acessar os dados.
pBuffer
[out] Um buffer no qual colocar os dados do registro atual.
Valor de retorno
Um valor HRESULT padrão.
Comentários
Para obter um exemplo de como usar essa função, consulte o Exemplo de MultiRead.
CRowset::GetOriginalData
Chama IRowsetUpdate::GetOriginalData
para recuperar os dados obtidos mais recentemente ou transmitidos para a fonte de dados.
Sintaxe
HRESULT GetOriginalData() throw();
Valor retornado
Um valor HRESULT padrão.
Comentários
Esse método recupera os dados do fetch mais recente ou transmitidos para a fonte de dados; não recupera valores com base em alterações pendentes.
Esse método requer a interface IRowsetUpdate
, opcional, que pode não ter suporte em todos os provedores; se esse for o caso, o método retornará E_NOINTERFACE. Você também deve definir DBPROP_IRowsetUpdate
como VARIANT_TRUE antes de chamar Open
sobre a tabela ou o comando que contém o conjunto de linhas.
CRowset::GetRowStatus
Retorna o status de todas as linhas.
Sintaxe
HRESULT GetRowStatus(DBPENDINGSTATUS* pStatus) const throw();
Parâmetros
pStatus
[out] Um ponteiro para um local onde GetRowStatus
retornará o valor de status. Consulte DBPENDINGSTATUS na Referência do programador OLE DB.
Valor de retorno
Um valor HRESULT padrão.
Comentários
Esse método requer a interface IRowsetUpdate
, opcional, que pode não ter suporte em todos os provedores; se esse for o caso, o método retornará E_NOINTERFACE. Você também deve definir DBPROP_IRowsetUpdate
como VARIANT_TRUE antes de chamar Open
sobre a tabela ou o comando que contém o conjunto de linhas.
CRowset::Insert
Cria e inicializa uma nova linha usando os dados do acessador.
Sintaxe
HRESULT Insert(int nAccessor = 0,
bool bGetHRow = false) throw();
Parâmetros
nAccessor
[in] O número do acessador a ser usado para inserir os dados.
bGetHRow
[in] Indica se o identificador da linha inserida foi recuperado.
Valor de retorno
Um valor HRESULT padrão.
Comentários
Esse método requer a interface IRowsetChange
, opcional, que pode não ter suporte em todos os provedores; se esse for o caso, o método retornará E_NOINTERFACE. Você também deve definir DBPROP_IRowsetChange
como VARIANT_TRUE antes de chamar Open
sobre a tabela ou o comando que contém o conjunto de linhas.
A inserção poderá falhar se uma ou mais colunas não forem graváveis. Modifique seu mapa de cursor para corrigir isso.
Exemplo
O exemplo a seguir mostra como acessar uma fonte de dados por meio de um conjunto de linhas e, em seguida, inserir uma cadeia de caracteres usando uma tabela no conjunto de linhas.
Primeiro, crie uma classe de tabela inserindo um novo objeto ATL em seu projeto. Por exemplo, clique com o botão direito do mouse no projeto no painel workspace e selecione Novo Objeto ATL. Na categoria Acesso a Dados, selecione Consumidor. Crie um objeto de consumidor do tipo Tabela. (Selecionar Tabela cria um conjunto de linhas diretamente da tabela; selecionar Comando cria um conjunto de linhas por meio de um comando SQL). Selecione uma fonte de dados, especificando uma tabela por meio da qual acessar a fonte de dados. Se você chamar o objeto de consumidor CCustomerTable, implementará o código de inserção da seguinte maneira:
// Access the rowset using the wizard-generated class, CCustomerTable
CCustomerTable rs; // Your CTable-derived class
// Insert a customer
// Note that for fixed-length fields such as billing ID it isn't necessary
// to set the length
rs.m_BillingID = 5002;
rs.m_dwBillingIDStatus = DBSTATUS_S_OK;
_tcscpy_s(rs.m_ContactFirstName, sizeof(rs.m_ContactFirstName) / sizeof(TCHAR),
_T("Malcolm"));
rs.m_dwContactFirstNameLength = 7;
rs.m_dwContactFirstNameStatus = DBSTATUS_S_OK;
_tcscpy_s(rs.m_L_Name, sizeof(rs.m_L_Name) / sizeof(TCHAR), _T("Reynolds"));
rs.m_dwL_NameLength = 8;
rs.m_dwContactFirstNameStatus = DBSTATUS_S_OK;
rs.m_CustomerID = 2005;
rs.m_dwCustomerIDStatus = DBSTATUS_S_OK;
_tcscpy_s(rs.m_PostalCode, sizeof(rs.m_PostalCode) / sizeof(TCHAR),
_T("34213-4444"));
rs.m_dwPostalCodeLength = 10;
rs.m_dwPostalCodeStatus = DBSTATUS_S_OK;
HRESULT hr = rs.Insert();
if (FAILED(hr))
{
ATLTRACE(_T("Insert failed: 0x%X\n"), hr);
}
CRowset::IsSameRow
Compara a linha especificada com a linha atual.
Sintaxe
HRESULT IsSameRow(HROW hRow) const throw();
Parâmetros
hRow
[in] Um identificador para a linha a ser comparada com a linha atual.
Valor de retorno
Um valor HRESULT padrão. S_OK indica que as linhas são as mesmas. Para outros valores, consulte IRowsetIndentity::IsSameRow na Referência do Programador OLE DB no SDK do Windows.
CRowset::MoveFirst
Move o cursor para a posição inicial e recupera a linha inicial.
Sintaxe
HRESULT MoveFirst() throw();
Valor retornado
Um valor HRESULT padrão.
Comentários
Chama IRowset::RestartPosition para reposicionar o local de fetch seguinte para a posição inicial (a posição que era o local de fetch seguinte quando o conjunto de linhas foi criado) e recupera a linha inicial.
CRowset::MoveLast
Move o cursor para a última linha.
Sintaxe
HRESULT MoveLast() throw();
Valor retornado
Um valor HRESULT padrão.
Comentários
Chama IRowset::RestartPosition para reposicionar o local de fetch seguinte para a última posição e recupera a última linha.
Esse método exige que você defina DBPROP_CANSCROLLBACKWARDS
como VARIANT_TRUE antes de chamar Open
na tabela ou no comando que contém o conjunto de linhas. (Para melhor desempenho, você também pode definir DBPROP_QUICKRESTART
como VARIANT_TRUE).
CRowset::MoveNext
Move o cursor para o próximo registro.
Sintaxe
HRESULT MoveNext() throw();
HRESULT MoveNext(LONG lSkip,
bool bForward= true) throw();
Parâmetros
lSkip
[in] O número de linhas a serem ignoradas antes do fetch.
bForward
[in] Passe true
para avançar para o próximo registro, false
para voltar para trás.
Valor de retorno
Um valor HRESULT padrão. Quando o final do conjunto de linhas for atingido, retornará DB_S_ENDOFROWSET.
Comentários
Efetua fetch da próxima linha sequencial do objeto CRowset
, lembrando a posição anterior. Opcionalmente, você pode optar por ignorar linhas lSkip ou voltar para trás.
Esse método exige que você defina as propriedades a seguir antes de chamar Open
na tabela ou no comando que contém o conjunto de linhas:
DBPROP_CANSCROLLBACKWARDS
deve ser VARIANT_TRUE se lSkip< 0DBPROP_CANFETCHBACKWARDS
deve ser VARIANT_TRUE se bForward = false
Caso contrário, (se lSkip>= 0 e bForward = true), você não precisará definir nenhuma propriedade adicional.
CRowset::MovePrev
Move o cursor para o registro anterior.
Sintaxe
HRESULT MovePrev() throw();
Valor retornado
Um valor HRESULT padrão.
Comentários
Esse método exige que você defina DBPROP_CANFETCHBACKWARDS
ou DBPROP_CANSCROLLBACKWARDS
como VARIANT_TRUE antes de chamar Open
na tabela ou no comando que contém o conjunto de linhas.
CRowset::MoveToBookmark
Efetua fetch da linha marcada por um indicador ou a linha em um deslocamento especificado (lSkip) desse indicador.
Sintaxe
HRESULT MoveToBookmark(const CBookmarkBase& bookmark,
LONG lSkip = 0) throw();
Parâmetros
bookmark
[in] Um indicador que marca o local do qual você deseja efetuar fetch dos dados.
lSkip
[in] A contagem de números de linhas do indicador para a linha de destino. Se lSkip for zero, a primeira linha buscada será a linha com indicador. Se lSkip for 1, a primeira linha buscada será a linha após a linha com indicador. Se lSkip for -1, a primeira linha buscada será a linha anterior à linha com indicador.
Valor de retorno
Um valor HRESULT padrão.
Comentários
Esse método requer a interface IRowsetLocate
, opcional, que pode não ter suporte em todos os provedores; se esse for o caso, o método retornará E_NOINTERFACE. Você também deve definir DBPROP_IRowsetLocate
como VARIANT_TRUE e DBPROP_CANFETCHBACKWARDS
como VARIANT_TRUE antes de chamar Open
na tabela ou no comando que contém o conjunto de linhas.
Para obter informações sobre como usar indicadores em consumidores, consulte Usando indicadores.
CRowset::MoveToRatio
Efetua fetch das linhas iniciando de uma posição fracionária no conjunto de linhas.
Sintaxe
HRESULT MoveToRatio(DBCOUNTITEM nNumerator,
DBCOUNTITEM nDenominator,bool bForward = true) throw();
Parâmetros
nNumerator
[in] O numerador usado para determinar o posicional fracionário do qual efetuar fetch dos dados.
nDenominator
[in] O denominador usado para determinar o posicional fracionário do qual efetuar fetch dos dados.
bForward
[in] Indica se deve mover para frente ou para trás. O padrão é para frente.
Valor de retorno
Um valor HRESULT padrão.
Comentários
Em termos gerais, MoveToRatio
efetua fetch de linhas de acordo com a fórmula a seguir:
(nNumerator * RowsetSize ) / nDenominator
onde RowsetSize
é o tamanho do conjunto de linhas, medido em linhas. A precisão dessa fórmula depende do provedor específico. Para obter detalhes, consulte IRowsetScroll::GetRowsAtRatio.
Esse método requer a interface IRowsetScroll
, opcional, que pode não ter suporte em todos os provedores; se esse for o caso, o método retornará E_NOINTERFACE. Você também deve definir DBPROP_IRowsetScroll
como VARIANT_TRUE antes de chamar Open
sobre a tabela ou o comando que contém o conjunto de linhas.
CRowset::ReleaseRows
Chama IRowset::ReleaseRows para liberar o identificador de linha atual.
Sintaxe
HRESULT ReleaseRows() throw();
Valor retornado
Um valor HRESULT padrão.
CRowset::SetData
Define valores de dados em uma ou mais colunas de uma linha.
Sintaxe
HRESULT SetData() const throw();
HRESULT SetData(int nAccessor) const throw();
Parâmetros
nAccessor
[in] O número do acessador a ser usado para acessar os dados.
Valor de retorno
Um valor HRESULT padrão.
Comentários
Para o formulário SetData
que não aceita argumentos, todos os acessadores são usados para atualização. Normalmente, você chama SetData
para definir valores de dados em colunas em uma linha e, em seguida, chama Atualização para transmitir essas alterações.
Esse método requer a interface IRowsetChange
, opcional, que pode não ter suporte em todos os provedores; se esse for o caso, o método retornará E_NOINTERFACE. Você também deve definir DBPROP_IRowsetChange
como VARIANT_TRUE antes de chamar Open
sobre a tabela ou o comando que contém o conjunto de linhas.
A operação de configuração poderá falhar se uma ou mais colunas não forem graváveis. Modifique seu mapa de cursor para corrigir isso.
CRowset::Undo
Desfaz todas as alterações feitas em uma linha desde o último fetch ou atualização.
Sintaxe
HRESULT Undo(DBCOUNTITEM* pcRows = NULL,
HROW* phRow = NULL,
DBROWSTATUS* pStatus = NULL) throw();
Parâmetros
pcRows
[out] Um ponteiro para o local em que Undo
retornará o número de linhas que tentou desfazer, se necessário.
phRow
[out] Um ponteiro para o local onde Undo
retornará uma matriz de identificadores para todas as linhas que tentou desfazer, se necessário.
pStatus
[out] Um ponteiro para o local onde Undo
retornará o valor de status da linha. Nenhum status será retornado se o pStatus for nulo.
Valor de retorno
Um valor HRESULT padrão.
Comentários
Esse método requer a interface IRowsetUpdate
, opcional, que pode não ter suporte em todos os provedores; se esse for o caso, o método retornará E_NOINTERFACE. Você também deve definir DBPROP_IRowsetUpdate
como VARIANT_TRUE antes de chamar Open
sobre a tabela ou o comando que contém o conjunto de linhas.
CRowset::Update
Transmite todas as alterações pendentes feitas na linha atual desde o último fetch ou chamada de Update
.
Sintaxe
HRESULT Update(DBCOUNTITEM* pcRows = NULL,
HROW* phRow = NULL,
DBROWSTATUS* pStatus = NULL) throw();
Parâmetros
pcRows
[out] Um ponteiro para o local em que Update
retornará o número de linhas que tentou atualizar, se necessário.
phRow
[out] Um ponteiro para o local em que Update
retornará o identificador da linha que tentou atualizar. Nenhum identificador será retornado se phRow for nulo.
pStatus
[out] Um ponteiro para o local onde Update
retornará o valor de status da linha. Nenhum status será retornado se o pStatus for nulo.
Valor de retorno
Um valor HRESULT padrão.
Comentários
Transmite todas as alterações pendentes feitas para a linha atual desde a última vez que essa linha foi buscada ou atualizada pela última vez (usando Update
ou UpdateAll). Normalmente, você chama SetData para definir valores de dados em colunas de uma linha e, em seguida, chama Update
para transmitir essas alterações.
Esse método requer a interface IRowsetUpdate
, opcional, que pode não ter suporte em todos os provedores; se esse for o caso, o método retornará E_NOINTERFACE. Você também deve definir DBPROP_IRowsetUpdate
como VARIANT_TRUE antes de chamar Open
sobre a tabela ou o comando que contém o conjunto de linhas.
CRowset::UpdateAll
Transmite todas as alterações pendentes feitas em todas as linhas desde o último fetch ou chamada de Update
.
Sintaxe
HRESULT UpdateAll(DBCOUNTITEM* pcRows = NULL,
HROW** pphRow = NULL,
DBROWSTATUS** ppStatus = NULL) throw();
Parâmetros
pcRows
[out] Um ponteiro para o local em que UpdateAll
retornará o número de linhas que tentou atualizar, se necessário.
pphRow
[out] Um ponteiro para a memória no qual UpdateAll
retornará o identificador da linha que tentou atualizar. Nenhum identificador será retornado se pphRow for nulo.
ppStatus
[out] Um ponteiro para o local onde Update
retornará o valor de status da linha. Nenhum status será retornado se ppStatus for nulo.
Comentários
Transmite todas as alterações pendentes feitas a todas as linhas desde o último fetch ou da última atualização usando Update ou UpdateAll
. UpdateAll
atualizará todas as linhas que foram modificadas, independentemente de você ainda ter o identificador para elas (consulte pphRow) ou não.
Por exemplo, se você usava Insert
para inserir cinco linhas em um conjunto de linhas, poderia chamar Update
cinco vezes ou chamar UpdateAll
uma vez para atualizar todas elas.
Esse método requer a interface IRowsetUpdate
, opcional, que pode não ter suporte em todos os provedores; se esse for o caso, o método retornará E_NOINTERFACE. Você também deve definir DBPROP_IRowsetUpdate
como VARIANT_TRUE antes de chamar Open
sobre a tabela ou o comando que contém o conjunto de linhas.
Valor de retorno
Um valor HRESULT padrão.
Confira também
DBViewer Sample
MultiRead Sample
MultiRead Attributes Sample
Modelos de consumidor OLE DB
Referência de modelos de consumidor do OLE DB