CORRECÇÃO: Armazenar um conjunto de registos ADO no GIT pode causar uma violação de acesso

Artigo: 249175 - Ver produtos para os quais este artigo se aplica.
Expandir tudo | Reduzir tudo

Nesta página

Sintomas

O parágrafo seguinte é retirado do da base de dados de conhecimento da Microsoft artigo 248287, "Noções sobre ADO autenticação", que descreve o potencial problema de com a tabela de interface global COM conjuntos de registos do ActiveX Data Objects (ADO).

"COM fornece um componente denominado a tabela de interface global (GIT). O GIT permite que uma aplicação armazenar uma referência a interface um objecto na tabela de modo a que o apontador de interface pode ser obtido em qualquer altura. Quando armazenar o apontador de interface para o GIT, o objecto é consultado para IMarshal e se IMarshal é exposta pelo objecto, os dados de empacotamento de referências do objecto são colocados numa sequência onde podem ser obtida posteriormente algumas quando é obtido o apontador de interface. IMarshal é exposta pelo cursor de cliente que efectua realmente a transmissão de dados do conjunto de registos. Existe um problema se um objecto de conjunto de registos ADO aberto que utiliza adUseClient é colocado no GIT e, em seguida, mais tarde é revogado a partir da tabela. Ocorrerá um erro de violação de acesso. Para evitar este problema, coloque o apontador de interface de conjunto de registos no GIT antes de chamar abrir o conjunto de registos. Isto colocará o apontador de interface para o GIT antes do motor do cursor de cliente é invocado que causará essencialmente padrão de empacotamento de referências para ocorrer em vez de dados de registo a ser transmitido em sequência a partir do motor do cursor através de IMarshal. Apenas um ponteiro para a interface do conjunto de registos ADO será armazenado neste caso que é a intenção do programador real."

Resolução

Para evitar uma violação de acesso no código que pode quer aplicar a correcção listada neste artigo ou pode utilizar uma das seguintes soluções:
  • Não utilize um cursor do lado do cliente.

    - ou -

  • Armazene o conjunto de registos no GIT antes de abrir o conjunto de registos.
Nota : uma vez que ADO desligados conjuntos de registos requerem um cursor do lado do cliente, pode utilizar a primeira solução. No entanto, a segunda medida funciona se estiver a utilizar o conjunto de registos do ADO. Abrir () para abrir o conjunto de registos, mas não irá funcionar para a ligação . ( Executar ) ou ligações . OpenSchema () métodos se o conjunto de registos devolvido já estiver aberto. Nesse caso, a solução é um pouco complicada.

Se uma chamada para um método de ADO devolve um conjunto de registos que já esteja aberto, pode utilizar os seguintes passos para contornar o problema:

  1. Manter o objecto de conjunto de registos num ficheiro ou objecto de memória IPersistStream. Para manter um conjunto de registos ADO para um ficheiro, utilize o conjunto de registos . Guardar método (). Para manter um conjunto de registos ADO para IPersistStream, consulte o seguinte artigo na base de dados de conhecimento da Microsoft:
    242249Guardar um conjunto de registos ADO para um IStream
  2. Criar instância de um novo objecto de conjunto de registos ADO.
  3. Armazene o novo conjunto de registos no GIT utilizando o método de () RegisterInterfaceInGlobal .
  4. Carregar o novo objecto de conjunto de registos a partir dos dados persistentes no passo 1.

Ponto Da Situação

A Microsoft confirmou que este é um problema nos produtos da Microsoft listados no início deste artigo.

Este problema foi corrigido no MDAC 2.6.
Agora é disponibilizada pela Microsoft uma correcção suportada, mas destina-se apenas a corrigir o problema descrito neste artigo. Aplique-a apenas em sistemas que tenham este problema específico. Esta correcção poderá submetida a testes adicionais. Por conseguinte, se não estiver a ser gravemente afectado por este problema, recomendamos que aguarde pela próxima versão de Microsoft Data Access Components que contenha esta correcção.

Para resolver este problema imediatamente, contacte o suporte técnico da Microsoft para obter a correcção. Para obter uma lista completa de números de telefone do suporte técnico da Microsoft e informações sobre os custos de suporte, visite o seguinte Web site da Microsoft:
http://support.microsoft.com/contactus/?ws=support
Nota : em casos especiais, os custos normalmente inerentes às chamadas de suporte poderão ser anulados se um técnico de suporte da Microsoft determinar que uma actualização específica resolverá o problema. Os custos de suporte normais se aplicarão perguntas de suporte adicionais e problemas que não se enquadrem na atualização específica em questão.

A versão inglesa desta correcção deverá ter os seguintes atributos de ficheiro ou posteriores:
   Date         Time    Version       Size      File Name     Platform
   --------------------------------------------------------------------

   05/04/2000   19:32   2.51.5303.1   327,952   Msadce.dll    x86 
   05/03/2000   19:31   2.51.5303.0   487,696   Msado15.dll   x86 

Mais Informação

Passos para reproduzir o comportamento

  1. Criar um novo projecto no Microsoft Visual C++ e adicionar o seguinte código ao projecto:

    #import "C:\Program Files\Common Files\System\ado\msado15.dll" no_namespace
    //you may need to add proper code to make this complete
    //Open a Connection
    hr = pConn->Open("DSN=Datasource1", "UserID1", "PWD1", -1);
    if (SUCCEEDED(hr)) 
    {
    	//Use client side cursor
    	pConn->PutCursorLocation(adUseClient);
    
    	// Now Open an ADO Recordset
    	pRecordSet = pConn->Execute("jobs", &recs, -1);
    
    	// Store the recordset in GIT 
    	hr =  gGlobalIntTable->RegisterInterfaceInGlobal(pRecordSet, IID_IDispatch, &cookie);
    
    	// Now revoke from GIT (to see the crash!)
    	if (hr == S_OK)
    		hr = gGlobalIntTable->RevokeInterfaceFromGlobal(cookie); //Crash!!!
    
    	// Close the ADO Recordset 
    	pRecordSet->Close();
    }
  2. Se executar o código anterior, receberá um erro fatal na chamada RevokeInterfaceFromGlobal(). O seguinte código corrige o problema:
    	// Open a Connection
    	hr = pConn->Open("DSN=Datasource1", "UserID1", "PWD1", -1);
    	if (SUCCEEDED(hr)) 
    	{
    		// Now Open an ADO Recordset
    		pConn->PutCursorLocation(adUseClient);
    		pRecordSet = pConn->Execute("jobs", &recs, -1);
    
    		//Save this Recordset in a file
    		remove("c:\\mytemp.tmp");<BR/>
    
    		hr= pRecordSet->Save("c:\\mytemp.tmp",adPersistADTG);
                      //Close the ADO Recordset we don't use this anymore
    		pRecordSet->Close();
    		
    		//Now Create a new recordset
    		_RecordsetPtr pRECORDSET2(__uuidof(Recordset));
    
    		// Store the SECOND recordset in GIT 
    		hr =  gGlobalIntTable->RegisterInterfaceInGlobal(pRECORDSET2, IID_IDispatch, &cookie);
    
    		// Load the SECOND recordset from the persisted 
    		hr =  pRECORDSET2->Open("c:\\mytemp.tmp", vtMissing, adOpenStatic, adLockUnspecified, -1);
    
    		// Now revoke from GIT
    		if (hr == S_OK)
    			hr = gGlobalIntTable->RevokeInterfaceFromGlobal(cookie); 
    
    	}
    

    Tenha em atenção que o segundo conjunto de registos que foi criado sem utilizar o cursor do lado do cliente funciona correctamente.

Referências

  • CLSID_StdGlobalInterfaceTable
  • Tabela de interface global
  • Excepção não processada
  • R6025
  • Chamada de função virtual puro

Propriedades

Artigo: 249175 - Última revisão: sexta-feira, 7 de Abril de 2006 - Revisão: 2.0
A informação contida neste artigo aplica-se a:
  • Microsoft ActiveX Data Objects 2.1
  • Microsoft ActiveX Data Objects 2.5
Palavras-chave: 
kbmt kbqfe kbhotfixserver kbado260fix kbbug kbfix kbmdacnosweep kbwin2000sp1fix KB249175 KbMtpt
Tradução automática
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 revisto ou traduzido por humanos. A Microsoft tem artigos traduzidos por aplicações (MT) e artigos traduzidos por tradutores profissionais. O objectivo é simples: oferecer em Português a totalidade dos artigos existentes na base de dados do suporte. Sabemos no entanto que a tradução automática não é sempre perfeita. Esta pode conter erros de vocabulário, sintaxe ou gramática? erros semelhantes aos que um estrangeiro realiza ao falar em Português. A Microsoft não é responsável por incoerências, erros ou estragos realizados na sequência da utilização dos artigos MT por parte dos nossos clientes. A Microsoft realiza actualizações frequentes ao software de tradução automática (MT). Obrigado.
Clique aqui para ver a versão em Inglês deste artigo: 249175
Exclusão de Responsabilidade para Conteúdo sem Suporte na KB
Este artigo foi escrito sobre produtos para os quais a Microsoft já não fornece suporte. Por conseguinte, este artigo é oferecido "tal como está" e deixará de ser actualizado.

Submeter comentários