Problemas conhecidos para o ADODB PIA Primary Interop Assembly () incluída no Visual Studio 2005

Traduções de Artigos Traduções de Artigos
Artigo: 910696 - Ver produtos para os quais este artigo se aplica.
atenção ADO and ADO MD não foram totalmente testados num ambiente de Microsoft .NET Framework. Podem provocar problemas intermitentes, especialmente nas aplicações baseadas em serviços ou nas aplicações multithread. As técnicas que são discutidas neste artigo só devem ser utilizadas como uma medida temporária durante a migração para ADO.NET. Só deverá utilizar estas técnicas depois realizados concluída testar para se certificar que estão sem problemas de compatibilidade. Problemas causados por utilizar ADO ou ADO MD desta forma não são suportados. Para mais informações, consulte o seguinte artigo na base de dados de conhecimento da Microsoft:
840667 É apresentada erros inesperados quando utilizar o ADO and ADO MD numa aplicação do .NET Framework
Expandir tudo | Reduzir tudo

Nesta página

INTRODUÇÃO

Este artigo descreve as questões conhecidas para o ADODB PIA Primary Interop Assembly () incluída no Microsoft Visual Studio 2005.

Mais Informação

Diferenças no recolha de dados entre o Microsoft Visual Basic 6.0 e Microsoft Visual Basic .NET

Existirem diferenças principais entre recolha de dados no Visual Basic 6.0 e no Visual Basic. NET. A principal diferença é que recolha de dados do Visual Basic 6.0 é mais agressivo de recolha de dados Visual Basic. NET. Com o Visual Basic 6.0, assim que uma instância de objecto ficar fora do âmbito, o objeto será liberado imediatamente. O mesmo comportamento não ocorre com o Visual Basic .NET ou com recolha de lixo .NET normal. Com a recolha de lixo .NET objectos são libertados assincronamente.

A diferença na recolha de dados pode ter um grande efeito no código de acesso a dados quando move a partir do Visual Basic 6.0 para o Visual Basic. NET.

Por exemplo, um objecto ADODB Recordset aberto é fechado quando o objecto é recolhido pela colecção de elementos não utilizados. Os programadores que tenham experiência escrever código Visual Basic 6.0 podem depender de semântica de recolha de lixo será alterado quando que migrar código para o Visual Basic. NET. Uma vez que recolha de lixo .NET é assíncrona e não determinista, poderá não ver as alterações mesmo após testes básicos.

Algumas bases de dados, tais como bases de dados do Microsoft SQL Server 2000, só suportam um único resultado activo por ligação. Se tiver um cursor firehose abertos numa ligação para o SQL Server, que ligação está bloqueada até que o cursor seja fechado. Por predefinição, fornecedores de OLE DB irão aberta ligações adicionais para executar consultas se a ligação actual não é possível executar essa consulta. Deste modo, muitos utilizadores de ActiveX Data Objects (ADO) são não utilizam esta limitação. Estas ligações adicionais não participar num agrupamento de ligações. Tentativas para abrir ligações adicionais quando a ligação bloqueada está a participar numa transacção falhará.

Recomendamos que reveja o código de Visual Basic 6.0 e explicitamente feche todos os objectos de conjunto de registos e ligações. Em seguida, teste novamente o código depois de migrar o código para o Visual Basic. NET.

Esta secção apresenta três exemplos desta questão e exemplos de código para cada exemplo.

Exemplo 1: Abrir o ligações adicionais quando explicitamente não fechar os objectos conjunto de registos

Quando executa o seguinte exemplo de código no Visual Basic 6.0, é necessária apenas uma única ligação. Isto acontece porque o objecto de conjunto de registos que criou no procedimento ExecuteQuery implicitamente é fechado quando o objeto Recordset ficar fora do âmbito. O exemplo de código utiliza a variável de servidor SQL @@ SPID para representar o identificador de processo do servidor que é utilizado para executar a consulta. Se executar o código, irá notar que as consultas devolvem o mesmo valor no @@ spid coluna. Este resultado significa que as consultas foram executar na mesma ligação à base de dados.
Public Sub Main()
    Dim strConn As String
    Dim cn As ADODB.Connection
    
    strConn = "Provider=SQLOLEDB;Data Source=.;" & _
              "Initial Catalog=Northwind;Trusted_Connection=Yes;"
    
    Set cn = New ADODB.Connection
    cn.Open strConn
    
    cn.Properties("Multiple Connections").Value = False
    
    ExecuteQuery cn, "SELECT @@spid, * FROM Customers"
    ExecuteQuery cn, "SELECT @@spid, * FROM Customers"
End Sub

Private Sub ExecuteQuery(cn As ADODB.Connection, strSQL As String)
    Dim rs As ADODB.Recordset
    Set rs = cn.Execute(strSQL)
    MsgBox rs(0)
End Sub
se utilizar código semelhante no Visual Basic. NET, notará que o objecto de conjunto de registos segundo contém um valor diferente para @@ spid coluna. Este valor significa que a consulta foi executada numa ligação diferente para a base de dados.

Este comportamento é diferente porque o objecto de conjunto de registos que foi criado no procedimento ExecuteQuery não foi fechado e permanecerá aberto até que o recolector de lixo .NET limpa o objeto Recordset . Recolha de dados no Microsoft .NET Framework ocorre de forma assíncrona. Se o objecto de conjunto de registos não foi fechado a altura em que o procedimento ExecuteQuery é invocado novamente, o SQL Server fornecedor de OLE DB abrirá uma nova ligação para executar a segunda consulta.

Se adicionar uma chamada para o comando rs.Close no procedimento ExecuteQuery , certifique-se de que as consultas são executadas na mesma ligação. Pode saber também explicitamente o SQL Server fornecedor OLE DB não para abrir ligações adicionais. Para tal, adicione a seguinte linha de código imediatamente depois de abrir a ligação:
cn.Properties("Multiple Connections").Value = False
este código faz com que o SQL Server fornecedor OLE DB accionar uma excepção sempre o fornecedor de OLE DB caso contrário, iria abrir ligações adicionais.

Exemplo 2: Problemas ocorrem quando trabalha com transacções se não fechar explicitamente os objectos conjunto de registos

Não é possível abrir ligações adicionais quando a ligação bloqueada está a participar numa transacção. Quando executa o seguinte exemplo de código no Visual Basic 6.0, o código executa consultas múltiplas numa única ligação que tenha uma transacção aberta. O código chama duas funções:
  • GetCustomers
  • GetOrders
Cada função abre um objecto Recordset .
Public Sub Main()
    Dim cn As ADODB.Connection
    Set cn = New ADODB.Connection
    cn.Open "Provider=SQLOLEDB;Data Source=.;" & _
            "Initial Catalog=Northwind;Trusted_Connection=Yes;"
    
    cn.BeginTrans
    
    GetCustomers cn
    GetOrders cn
    
    cn.RollbackTrans
    cn.Close
End Sub

Public Sub GetCustomers(Connection As ADODB.Connection)
    Dim rs As ADODB.Recordset
    Set rs = Connection.Execute("SELECT CustomerID, CompanyName FROM Customers")
End Sub

Public Sub GetOrders(Connection As ADODB.Connection)
    Dim rs As ADODB.Recordset
    Set rs = Connection.Execute("SELECT OrderID, CustomerID FROM Orders")
End Sub
o objecto de conjunto de registos que é criado ao chamar a função GetCustomers implicitamente está fechado no fim dessa chamada de função no Visual Basic 6.0. Este comportamento é descrito de "exemplo 1: ligações adicionais abrir quando explicitamente não fechar os objectos conjunto de registos" secção. No entanto, esse objecto de conjunto de registos não pode ser fechado pelo tempo que o código chama a função GetOrders no Visual Basic. NET. Por conseguinte, a ligação actual para o SQL Server tem um resultado aberto com informações de cliente. Porque a ligação actual está ocupada, obter os resultados da consulta na função GetOrders requer uma nova criadas implicitamente a ligação. No entanto, não é possível criar uma ligação implícita enquanto uma transacção estiver aberta. Assim, o código irá falhar e receberá a seguinte mensagem de erro:
Não é possível criar nova ligação porque no modo de transacção manual ou distribuído.
Para resolver este problema, feche explicitamente os objectos de conjunto de registos que foram criados utilizando as funções GetCustomers e GetOrders .

Exemplo 3: Problemas ocorrem quando implicitamente criar e, em seguida, abandonar os objectos conjunto de registos

Por predefinição, o método execute dos objectos de ligação e comando implicitamente cria e devolve um novo objecto de conjunto de registos . No Visual Basic 6.0, se este objecto de conjunto de registos não é mantido numa variável de objecto, o objeto Recordset ficar fora do âmbito e é imediatamente fechado. Por este motivo, o seguinte exemplo de código executa com êxito no Visual Basic 6.0. No entanto, receberá a mensagem de erro mencionada de "exemplo 2: problemas ocorrem quando trabalha com transacções se não fechar explicitamente os objectos conjunto de registos" secção se o código for migrado para o Visual Basic .NET.
Dim cn As ADODB.Connection
Set cn = New ADODB.Connection
cn.Open "Provider=SQLOLEDB;Data Source=.;" & _
        "Initial Catalog=Northwind;Trusted_Connection=Yes;"

cn.BeginTrans

cn.Execute "SELECT CustomerID, CompanyName FROM Customers"
cn.Execute "SELECT OrderID, CustomerID FROM Orders ORDER BY CustomerID"

cn.RollbackTrans
cn.Close
neste exemplo de código, as chamadas para o método execute do objeto Connection implicitamente devolvem os objectos de conjunto de registos . Recolha de dados no Visual Basic 6.0 fecha imediatamente cada objecto de conjunto de registos , porque o valor de retorno não está armazenado numa variável. Recolha de dados não está como agressivo no Visual Basic. NET. O objecto de conjunto de registos que contém informações de cliente é ainda aberto quando ocorre a chamada para consultar a base de dados para informações sobre encomendas. Por conseguinte, recebe a mensagem de erro mencionada de "exemplo 2: problemas ocorrem quando trabalha com transacções se não fechar explicitamente os objectos conjunto de registos" secção.

Para resolver este problema, passar o valor adExecuteNoRecords do valor ExecuteOptionsEnum no parâmetro Opções do método de execução . Quando o fizer, pode indicar que o método execute não deverá devolver um objecto de conjunto de registos tal como ilustrado no seguinte código exemplo
cn.Execute "SELECT CustomerID, CompanyName FROM Customers", , _
           ADODB.ExecuteOptionsEnum.adExecuteNoRecords

Problema 2: Microsoft não recomenda a PIA ADODB para cenários de pressão

É vivamente desencorajar utilizem a PIA ADODB em cenários de importância, como, por exemplo, nos componentes do Microsoft ASP.NET ou Microsoft COM + multi-utilizador. Quando as equipas de teste do Microsoft testou a PIA ADODB, encontrar as equipas de teste que a PIA ADODB falha em importância. Se o código de acesso de dados .NET tem de executar eficazmente em limite, recomendamos vivamente que escrever o código utilizando ADO.NET.

Problema 3: Microsoft não recomenda que utilize a PIA ADODB no modo de 64 bits

É vivamente desencorajar utilizem a PIA ADODB em aplicações de 64 bits. Não foi testada a PIA ADODB no modo de 64 bits. A maior parte dos cenários de 64 bits envolvem componentes de lado do servidor muito exigentes, tais como o ASP.NET ou COM +. A PIA ADODB tem conhecidos problemas em execução sob pressão. A disponibilidade limitada de fornecedores de OLE DB 64-bit também torna o modo de 64 bits menos apelativas para trabalhar com a PIA ADODB.

Problema 4: Falhas ocorrem quando utiliza execução da consulta atrasado dependente

ADODB suporta duas formas de execução da consulta atrasado dependente. Execução da consulta atrasado dependente permite-lhe utilizar o enlace de IDispatch COM para executar consultas como se as consultas foram métodos no objecto de ligação . ADODB suporta os seguintes dois formulários de execução da consulta atrasado dependente:
  • Crie uma consulta "nome" definindo a propriedade nome do objecto Command .
  • Execute uma chamada de procedimento armazenado.
Poderá detectar problemas com estes formulários quando migrar código do Visual Basic 6.0 para o Visual Basic. NET.

Os exemplos seguintes ilustram estes problemas.

Exemplo 1: Se criar uma segunda consulta atrasado dependente que tenha o mesmo nome, a consulta falha

O exemplo de código seguinte cria duas consultas atrasado dependentes que utilizam o mesmo valor para a propriedade Name do objecto Command .
Dim cn As ADODB.Connection
Dim cmd As ADODB.Command
Dim rs As ADODB.Recordset
Dim strConn As String
    
'Open a new Connection.
strConn = "Provider=SQLOLEDB;Data Source=.;" & _
          "Initial Catalog=Northwind;Trusted_Connection=Yes"
Set cn = New ADODB.Connection
cn.Open strConn
    
'Create a Command object, and then set the Name property 
'to enable the Command object as a late-bound method call.
Set cmd = New ADODB.Command
cmd.CommandText = "SELECT COUNT(*) FROM Customers"
cmd.Name = "GetCount"
Set cmd.ActiveConnection = cn
    
'Execute the Command object as a late-bound method call on the Connection.
Set rs = New ADODB.Recordset
cn.GetCount rs
Debug.Print rs(0).Value
rs.Close
Set rs = Nothing
    
'Release the Command object.
Set cmd = Nothing
    
'Create a new Command object, and then set the Name property
'to enable the Command object as a late-bound method call.
Set cmd = New ADODB.Command
cmd.CommandText = "SELECT COUNT(*) FROM Orders"
cmd.Name = "GetCount"
Set cmd.ActiveConnection = cn
    
'Execute the Command object as a late-bound method call on the Connection object.
Set rs = New ADODB.Recordset
cn.GetCount rs
Debug.Print rs(0).Value
rs.Close
Set rs = Nothing
    
'Clean up.
cn.Close
no Visual Basic 6.0, assim que o objecto de comando estiver definido para nada, o objecto é recolhido pela colecção de elementos não utilizados. O objecto de ligação é notificado que o objecto Command tem sido destruído. Por conseguinte, quando o segundo objecto Command é associado ao objecto de ligação , não existe nenhum conflito.

Quando é executado código semelhante no Visual Basic. NET, o objecto Command poderá não ser reclamado pela colecção de elementos não utilizados na altura em que o segundo comando objecto está associado o objeto Connection . Por conseguinte, poderá receber a seguinte mensagem de excepção:
Objecto já existe na colecção. Não é possível acrescentar.
Para resolver este problema, desassociar manualmente o objecto Command primeiro do objecto de ligação . Para efectuar este procedimento, chame explicitamente o método cmd.ActiveConnection quando limpar o objecto Command . Para o fazer, utilize o seguinte exemplo de código.
'Visual Basic 6.0 syntax
Set cmd.ActiveConnection = Nothing

'Visual Basic .NET syntax
cmd.ActiveConnection = Nothing

Exemplo 2: Se contactar uma consulta atrasado dependente numa segunda ligação, a consulta falha

O seguinte exemplo de código executa as seguintes tarefas pela ordem em que são apresentados:
  1. Crie dois objectos de ligação .
  2. Crie um objecto comandos em cada ligação de objecto. Cada objecto de comando tem o mesmo valor para a propriedade Name .
  3. Execute cada comando, utilizando a execução da consulta atrasado dependente.
Dim strConn As String, strSQL As String
Dim cn1 As ADODB.Connection, cn2 As ADODB.Connection
Dim cmd1 As ADODB.Command, cmd2 As ADODB.Command
Dim rs1 As ADODB.Recordset, rs2 As ADODB.Recordset
    
strConn = "Provider=SQLOLEDB;Data Source=.;" & _
          "Initial Catalog=Northwind;Trusted_Connection=Yes;"
strSQL = "SELECT COUNT(*) FROM Customers"
    
'Open connections.
Set cn1 = New ADODB.Connection
Set cn2 = New ADODB.Connection
cn1.Open strConn
cn2.Open strConn
    
'Create commands so that the commands can be executed as late-bound methods.
Set cmd1 = New ADODB.Command
Set cmd2 = New ADODB.Command
cmd1.CommandText = strSQL
cmd2.CommandText = strSQL
cmd1.Name = "GetCount"
cmd2.Name = "GetCount"
Set cmd1.ActiveConnection = cn1
Set cmd2.ActiveConnection = cn2
    
'Execute queries as late-bound methods.
Set rs1 = New ADODB.Recordset
Set rs2 = New ADODB.Recordset
cn1.GetCount rs1
cn2.GetCount rs2
MsgBox rs1(0).Value
MsgBox rs2(0).Value
    
'Clean up.
rs1.Close
rs2.Close
cn1.Close
cn2.Close
Este exemplo de código for bem sucedida quando utiliza o Visual Basic 6.0. No entanto, este exemplo de código falhará quando utiliza o Visual Basic. NET. Esta falha ocorre porque das seguintes razões:
  • Como ADODB prepara estas consultas como métodos de atrasado dependente
  • Pressupostos que faz com que o compilador de Visual Basic .NET sobre estes métodos
Quando definir a propriedade LigaçãoActiva (ActiveConnection) do objecto Command , ADODB verifica se o objecto Command tem a propriedade de nome definido. Se a propriedade ' nome estiver definida, ADODB prepara a consulta para que a consulta pode ser executada como um método atrasado dependentes no objecto de ligação . Neste exemplo, os dois objectos comando têm o mesmo valor para a propriedade CommandText . No entanto, este é um exemplo muito simplistic. Apesar dos objectos de comando de tem o mesmo valor para a propriedade Name , os objectos de comando podem ter CommandText valores que seria executado consultas muito diferentes. Por conseguinte, ADODB gera assinaturas de método exclusivo para os métodos atrasado dependente.

O compilador de Visual Basic .NET não efectua este diferenciação. Na primeira chamada para a consulta "GetCount", o compilador de Visual Basic .NET caches a assinatura de método caso é efectuada outra chamada para um método GetCount num objecto de ligação . Quando o código chama a segunda consulta "GetCount", o Visual Basic .NET reutiliza a assinatura de método em cache para o segundo método GetCount . Porque ADODB gera assinaturas de método exclusivo, a chamada para a segunda consulta atrasado ligação falha.

Não existem soluções existem para este cenário.

Problema 5: Pode definir alguns tipos de dados variante ADODB para tipos de dados de cadeia

O modelo de objecto ADODB permite-lhe definir algumas propriedades para cadeias de ou para outros objectos ADODB. Por exemplo, a propriedade LigaçãoActiva (ActiveConnection) do objecto Recordset é apresentado no Visual Basic 6.0 Object Browser como um tipo de dados Variant e pode ser definida para um objecto de ligação ou uma cadeia de ligação.

Se tiver criado o próprio objecto e pretende suportar esta funcionalidade, tem de criar os acessores de propriedade separado. Para o fazer, utilize código semelhante ao seguinte exemplo de código.
Public Property Let ActiveConnection (ByVal value As String)
    'Add logic here.
End Property

Public Property Set ActiveConnection (ByRef value As Object)
    'Add logic here.
End Property
o .NET Framework é um pouco mais rigorosas e não permite várias os acessores de propriedade com diferentes tipos de dados. A PIA ADODB permite-lhe definir a propriedade LigaçãoActiva (ActiveConnection) do objecto conjunto de registos para um objecto de ligação . Se pretender definir a propriedade ActiveConnection para uma cadeia, terá de utilizar o método let_ActiveConnection conforme ilustrado no seguinte exemplo de código.
Dim strConn As String
Dim rs As ADODB.Recordset
    
strConn = "Provider=SQLOLEDB;Data Source=.;" & _
          "Initial Catalog=Northwind;Trusted_Connection=Yes;"
rs = New ADODB.Recordset
rs.let_ActiveConnection(strConn)
a mesma abordagem é necessária quando definir as seguintes propriedades:
  • A propriedade origem do objecto Recordset
  • A propriedade ActiveConnection do objecto Command
Estas propriedades aceitam objectos. Para definir estas propriedades para cadeias, tem de utilizar o método let_ MethodName correspondente.

: 6 Uma excepção InvalidCastException acontece quando chamar o método Parameters.Append

A PIA ADODB incluída no Microsoft Visual Studio .NET 2003 e Visual Studio 2005 tem um problema conhecido que ocorre quando chamar o método de Parameters.Append juntamente com um objecto de parâmetro foi criado utilizando o construtor predefinido.

O seguinte exemplo de código causará uma excepção InvalidCastException . cmd
Dim cmd As ADODB.Command
Dim p As ADODB.Parameter

cmd = New ADODB.Command
cmd.CommandText = "SELECT CustomerID FROM Orders WHERE OrderID = ?"

p = New ADODB.Parameter
p.Name = "@OrderID"
p.Type = ADODB.DataTypeEnum.adInteger
p.Value = 10248

cmd.Parameters.Append(p)

para contornar este problema, crie os objectos de parâmetro utilizando o método CreateParameter do objeto Command , conforme ilustrado no seguinte exemplo de código. cmd
Dim cmd As ADODB.Command
Dim p As ADODB.Parameter

cmd = New ADODB.Command
cmd.CommandText = "SELECT CustomerID FROM Orders WHERE OrderID = ?"

p = cmd.CreateParameter()
p.Name = "@OrderID"
p.Type = ADODB.DataTypeEnum.adInteger
p.Value = 10248

cmd.Parameters.Append(p)

Problema 7: É problemas trabalhar com componentes que são supostas ADO 2.8 interfaces

A PIA ADODB incluída no Visual Studio 2005 é o mesmo componente que foi incluído no Visual Studio .NET 2003 e foi criado utilizando o Microsoft .NET Framework 1.1. A PIA ADODB foi concebida para interagir com o ADO 2.7 interfaces e não foi actualizada para trabalhar com o ADO 2.8 interfaces.

Por conseguinte, as tentativas para utilizar a PIA ADODB juntamente com os componentes que expõem ADO interfaces 2.8 irá falhar. Este cenário não é suportado com a PIA ADODB.

Propriedades

Artigo: 910696 - Última revisão: 28 de novembro de 2007 - Revisão: 2.1
A informação contida neste artigo aplica-se a:
  • Microsoft Visual Studio 2005 Professional
  • Microsoft Visual Studio 2005 Standard Edition
  • Microsoft Visual Studio 2005 Team System Architect Edition
  • Microsoft Visual Studio 2005 Team System Developer Edition
  • Microsoft Visual Studio 2005 Team System Team Foundation:
  • Microsoft Visual Studio 2005 Team System Test Edition
  • Microsoft Visual Studio 2005 Express Edition
Palavras-chave: 
kbmt kbinfo KB910696 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: 910696

Submeter comentários

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com