INFO: Usando ActiveX Data Objects (ADO) via # Import no VC ++

IMPORTANTE: Este artigo foi traduzido por um sistema de tradução automática (também designado por Machine Translation ou MT), não tendo sido portanto traduzido ou revisto por pessoas. A Microsoft possui artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais, com o objetivo de oferecer em português a totalidade dos artigos existentes na base de dados de suporte. No entanto, a tradução automática não é sempre perfeita, podendo conter erros de vocabulário, sintaxe ou gramática. A Microsoft não é responsável por incoerências, erros ou prejuízos ocorridos em decorrência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza atualizações freqüentes ao software de tradução automática (MT). Obrigado.

Clique aqui para ver a versão em Inglês deste artigo: 169496
Este artigo foi arquivado. É oferecido "como está" e não será mais atualizado.
Sumário
A diretiva # import no Visual C++ oferece um novo mecanismo eficiente para manipular servidores OLE. Quando usado com o ActiveX Data Objects (ADO), # Import pode simplificar obter seus dados. Este artigo descreve o que é necessário para tirar proveito de # import com o ADO.
Mais Informações

Antes de instanciar qualquer classes criado por # Import

É importante ao inicializar OLE antes de criar quaisquer instâncias de classes criadas por # Import. Por exemplo, o código a seguir é seguro, que declara um ponteiro inteligente # Import, inicializa OLE e, em seguida, instancia o ponteiro inteligente:

   // Declare smart pointer of Recordset    _RecordsetPtr     p;   void main( void )   {      // Initialize OLE.      ::CoInitialize(NULL);      // Instantiate smart pointer.      HRESULT hr = p.CreateInstance( __uuidof( Recordset ) );      ...   }				
Próximo exemplo de código, no entanto, não é seguro e gera uma exceção não tratada. O ponteiro inteligente global p é tanto declarado e instanciado (devido passando um uuid específico no construtor):

// Declare & instantiate smart pointer of Recordset    _RecordsetPtr     p( __uuidof( _Recordset ) );   void main( void )   {      // Initialize OLE      ::CoInitialize(NULL);      ...   }				
Porque p é uma variável global, ele é instanciado antes CoInitialize já é chamado no main(). Você pode corrigir isso com o seguinte trecho de código:
struct InitOle {      InitOle()  { ::CoInitialize(NULL); }      ~InitOle() { ::CoUninitialize();   }    } _init_InitOle_;   // Declare & instantiate smart pointer of Recordset    _RecordsetPtr     p( __uuidof( _Recordset ) );   ...				
Uma instância da estrutura InitOle é declarada e instanciado antes de p e, portanto, inicializa OLE no construtor é. Sem esse tipo de à prova de falhas, você verá a seguinte mensagem de erro:
Exceção no programa de [] (Kernel32.dll) sem tratamento: 0xE06D7363
Exceção do Microsoft C++.

Implementação correta de # import

É importante invocar ADO corretamente no seu programa, ou você pode ter erros do compilador. O código a seguir demonstra a maneira correta de usar # Import com Msado10.dll o MSADO15.dll:

   #import <msado15.dll>            \    no_namespace                     \   rename( "EOF", "adoEOF" )				

Tratamento de erros

Com o ADO, você pode receber um erro no HRESULT retornado de um método do ADO, você pode receber uma exceção gerada por classes # Import gerado e a coleção de erros de ADO para qualquer condição pode ser preenchida. Para obter a coleção de erros você precisa de um objeto de conexão válida. Para obter mais informações consulte o seguinte artigo na Base de dados de Conhecimento da Microsoft:

169498INFO: Extraindo informações de erro do ADO no VC ++ com # Import

ADO e Dbdaoint.h

Tenta misturar ADO (através de # import) e MFC DAO ou o SDK do DAO no mesmo arquivo de implementação, da seguinte maneira:

  #include <afxdao.h>  // MFC DAO   // -or-  #include <dbdao.h>   // DAO SDK  #import <msado15.dll> no_namespace ...				

Gera os seguintes seis erros:

Erro C2011: 'EditModeEnum': 'enum' digite redefinição
Erro C2011: 'LockTypeEnum': 'enum' digite redefinição
Erro C2011: 'FieldAttributeEnum': 'enum' digite redefinição
Erro C2011: 'DataTypeEnum': 'enum' digite redefinição
Erro C2011: 'ParameterDirectionEnum': 'enum' digite redefinição
Erro C2011: 'RecordStatusEnum': 'enum' digite redefinição
Enquanto o muito quase idênticas em conteúdo, os valores reais em cada tipo enumerado diferem entre o que é exigido pelo ADO e o que é exigido pelo DAO. Você tem várias opções para solucionar esse problema:

  • Código DAO e ADO separado em arquivos .cpp separado. Mantenha o uso de # Import ou # include <afxdao.h/dbdao.h> em arquivos de implementação separada também.
  • Modificar a instrução # import para criar um espaço para nome para qualquer coisa gerado para ADO. Isso significa que você terá que referenciar o namespace ao fazer referência um objeto ADO conforme as duas funções abaixo. O primeiro mostra como usar o ADO exclusivamente dentro de uma função. O segundo mostra como objetos DAO e ADO combinação e correspondência. Isso é possível apenas pela referência explicita o namespace do ADO para qualquer classe do ADO ou o tipo enumerado:

       #include <afxdao.h>      #import <msado15.dll>                            \               rename_namespace("AdoNS") rename( "EOF", "adoEOF" )      void ADOOnly( void )      {          using namespace AdoNS;          _RecordsetPtr   prs;          // Generates Compile Errors:          CDaoRecordset   rs;      }      void MixAdoAndDao( void )      {          AdoNS::_RecordsetPtr  prs;          // Compiles just fine          CDaoRecordset   drs;      }						
Msado105.tlh/Msado15.tli dissecting e usando--------------------------------------------

# Import gera dois arquivos, Msado105.tlh e Msado15.tli da typelib contido MSADO15.dll. A estrutura do arquivo .TLH pode ser dividida da seguinte maneira:
  • Encaminhar referências e definições de tipo
  • TypeDef ponteiro inteligente e declarações
  • Itens de biblioteca de tipo
Cada um é descrita detalhadamente abaixo.

Encaminhar referências e definições de tipo

Referências e definições de tipo direta são criadas através do uso de struct __declspec(uuid("...")) no GUID para qualquer dual interface, interface, e CoClass definidos no typelib.

   ...   struct __declspec(uuid("00000274-0000-0010-8000-00aa006d2ea4"))   /* dual interface */ _Connection;   ...   struct __declspec(uuid("00000275-0000-0010-8000-00aa006d2ea4"))   /* interface */ ICADOConnection;   ...   struct /* coclass */ Connection;   ...				
Nem todas as interfaces, como conexão, tem várias implementações. Isso depende da biblioteca de tipos, mas para ADO maioria das interfaces são duplo e não implementado como coclass ou interface.

Declaração de TypeDef ponteiro inteligente

Para interfaces e interfaces dual, ponteiros inteligentes são declarados, que simplifica muito usando a interface:
   ...   _COM_SMARTPTR_TYPEDEF(_Connection, __uuidof(_Connection));   ...   _COM_SMARTPTR_TYPEDEF(ICADOConnection, __uuidof(ICADOConnection));   ...				
Observe que nenhum ponteiro inteligente foi declarado para a interface conexão coclass.

Itens de biblioteca de tipo

Isso inclui qualquer tipos enumerados definidos em typelib, como bem implementação dos ponteiros inteligentes e itens de typelib:

enum CursorTypeEnum   {      adOpenUnspecified = -1,      adOpenForwardOnly = 0,      adOpenKeyset = 1,      adOpenDynamic = 2,      adOpenStatic = 3   };   ...   struct __declspec(uuid("00000274-0000-0010-8000-00aa006d2ea4"))   _Connection : _ADO   {      //       // Property data.      //       _declspec(property(get=GetConnectionString,                         put=PutConnectionString))      _bstr_t ConnectionString;      ...      //       // Wrapper methods for error-handling.      //       _bstr_t GetConnectionString ( );      void PutConnectionString (          _bstr_t pbstr );      ...      //       // Raw methods provided by interface.      //       virtual HRESULT __stdcall get_ConnectionString (          BSTR * pbstr ) = 0;      virtual HRESULT __stdcall put_ConnectionString (          BSTR pbstr ) = 0;      ...   };				
O fragmento de código anterior, a seção de dados de propriedade usa declspec para declarar get e coloque métodos de ConnectionString. A seção de métodos de invólucro fornece métodos criados pelo # Import, que dispor desses métodos e gerar uma exceção _com_error se eles não forem bem-sucedidos. A seção métodos RAW declara o método real que é chamado pela interface.

Enquanto você poderia chamar GetConnectionString ou PutConnectionString, não é realmente necessário. Como ConnectionString é uma propriedade você faria referência a ele da seguinte maneira:

   bstrConnect = SysAllocString( L"DSN=AdoDemo;UID=admin;PWD=sa" );   p->ConnectionString = bstrConnect;				


A implementação real do GetConnectionString/PutConnectionString pode ser encontrada no arquivo Msado15.tli.

Quando se trata de tempo para usar o objeto de conexão em seu código, você usaria uma instância do ponteiro inteligente para a interface dupla definida no Msado15.tlh, como a seguir:

   _ConnectionPtr p;   bstrConnect   HRESULT           hr = S_OK;   _ConnectionPtr    pConn;   hr = pConn.CreateInstance( __uuidof( Connection ) );      if( !FAILED( hr ) )         hr = pConn->Open( L"pubs", L"sa", L"" );				


Onde pubs é uma fonte de dados ODBC.

# Import e chamada Release() explicitamente

A vantagem de # import é que ele se encarrega de AddRef, QueryInterface e Release para você automaticamente. No entanto, se você decidir iniciar chamada Release() explicitamente, você pode criar problemas para si mesmo.

Em _com_ptr_t é m_pInterface de variável, um membro. Como # Import é um wrapper muito estreito, ele não faz distinção com m_pInterface após o o objeto é, na verdade, lançamento, versus apenas diminuindo sua referência contar sem realmente destruir o objeto. Chamando explicitamente versão ()--sem muito explicitamente chamada AddRef() para equilibrar it--# Import gladly tentará liberar um objeto que não existe, criação de efeitos colaterais interessantes e comportamento de falha.

As sugestões, você fez não AddRef() (ou pelo menos não precise), não liberá-lo ou.
Referências
  • Interno Com por Dale Rogerson ISBN 1-57231-349-8
  • O OLE COM objeto Viewer (Oleview.exe), que é fornecido com o Visual C++ para examinar o conteúdo de um typelib.
  • Documentação online do Visual C++: pesquisa na # Import
Para obter informações adicionais, clique nos números abaixo para ler os artigos na Base de dados de Conhecimento da Microsoft:
182389ARQUIVO: Adovcbm.exe ADO 1.5 com # Import e getrows/indicadores
184968FILE: Adovcsp.exe demonstra o uso de procedimentos com o ADO armazenados
186387EXEMPLO: Ado2atl.exe retorna ADO interfaces de COM
181733FILE: # Import Adovcbtd.exe usando UpdateBatch e CancelBatch
166112PROBLEMA: Conflito com o EOF ao usar o # Import com ADO
168354INFO: OLE subjacentes e erros de provedor OLEDB são expostos por meio do ADO
s_mfc

Aviso: este artigo foi traduzido automaticamente

Propriedades

ID do Artigo: 169496 - Última Revisão: 12/04/2015 17:09:38 - Revisão: 3.2

Microsoft ActiveX Data Objects 1.0, Microsoft ActiveX Data Objects 1.5, Microsoft ActiveX Data Objects 2.0, Microsoft ActiveX Data Objects 2.1, Microsoft ActiveX Data Objects 2.5, Microsoft ActiveX Data Objects 2.6, Microsoft Data Access Components 2.7

  • kbnosurvey kbarchive kbmt kbcode kbdatabase kbinfo kbusage KB169496 KbMtpt
Comentários