Definir as configurações de nível de conexão e comando da Camada de Acesso a Dados (VB)

por Scott Mitchell

Baixar código ou baixar PDF

Os TableAdapters em um conjunto de dados tipado automaticamente cuidam da conexão com o banco de dados, emitindo comandos e preenchendo uma DataTable com os resultados. No entanto, há ocasiões em que desejamos cuidar desses detalhes e, neste tutorial, aprendemos como acessar as configurações de nível de comando e de conexão do banco de dados no TableAdapter.

Introdução

Em toda a série de tutoriais, usamos conjuntos de dados tipados para implementar a camada de acesso de dado e os objetos comerciais de nossa arquitetura em camadas. Conforme discutido no primeiro tutorial, o conjunto de dados s de dataset tipado serve como repositórios de data, enquanto os TableAdapters atuam como wrappers para se comunicarem com o banco de dados para recuperar e modificar o dado subjacente. Os TableAdapters encapsulam a complexidade envolvida no trabalho com o banco de dados e nos poupa de ter que escrever código para se conectar ao banco de dados, emitir um comando ou preencher os resultados em uma DataTable.

No entanto, há ocasiões em que precisamos burrowr as profundidades do TableAdapter e escrever o código que funciona diretamente com os objetos ADO.NET. Nas modificações de banco de dados de disposição em um tutorial de transação, por exemplo, adicionamos métodos ao TableAdapter para iniciar, confirmar e reverter transações de ADO.net. Esses métodos usaram um objeto SqlTransaction interno criado manualmente que foi atribuído aos objetos de SqlCommand do TableAdapter.

Neste tutorial, examinaremos como acessar as configurações de nível de comando e de conexão de banco de dados no TableAdapter. Em particular, adicionaremos funcionalidade à ProductsTableAdapter que permite o acesso à cadeia de conexão subjacente e às configurações de tempo limite do comando.

Trabalhando com dados usando ADO.NET

O Microsoft .NET Framework contém uma infinidade de classes projetadas especificamente para trabalhar com dados. Essas classes, encontradas no namespaceSystem.Data, são chamadas de classes ADO.net . Algumas das classes sob a proteção ADO.NET estão vinculadas a um provedor de dadosespecífico. Você pode considerar um provedor de dados como um canal de comunicação que permite que as informações fluam entre as classes ADO.NET e o armazenamento de dados subjacente. Há provedores generalizados, como OleDb e ODBC, bem como provedores que são especialmente projetados para um sistema de banco de dados específico. Por exemplo, embora seja possível se conectar a um banco de dados de Microsoft SQL Server usando o provedor OleDb, o provedor SqlClient é muito mais eficiente, pois foi projetado e otimizado especificamente para SQL Server.

Ao acessar dados programaticamente, o padrão a seguir é normalmente usado:

  1. Estabeleça uma conexão com o banco de dados.
  2. Emita um comando.
  3. Para SELECT consultas, trabalhe com os registros resultantes.

Há classes ADO.NET separadas para executar cada uma dessas etapas. Para se conectar a um banco de dados usando o provedor SqlClient, por exemplo, use a classeSqlConnection. Para emitir um comando INSERT, UPDATE, DELETEou SELECT para o banco de dados, use a classeSqlCommand.

Exceto para as modificações de banco de dados em um tutorial de transação, não tivemos que escrever nenhum código ADO.net de baixo nível, por si só, porque o código gerado automaticamente pelo TableAdapters inclui a funcionalidade necessária para se conectar ao banco de dados, emitir comandos, recuperar dados e preencher esses dados em tabelas. No entanto, pode haver ocasiões em que precisamos personalizar essas configurações de nível baixo. Nas próximas etapas, examinaremos como explorar os objetos ADO.NET usados internamente pelos TableAdapters.

Etapa 1: examinando com a propriedade Connection

Cada classe TableAdapter tem uma propriedade Connection que especifica informações de conexão de banco de dados. Esse tipo de dados s de propriedade e ConnectionString valor são determinados pelas seleções feitas no assistente de configuração do TableAdapter. Lembre-se de que quando adicionamos primeiro um TableAdapter a um DataSet tipado, esse assistente nos solicita a fonte do banco de dados (veja a Figura 1). A lista suspensa nessa primeira etapa inclui os bancos de dados especificados no arquivo de configuração, bem como quaisquer outros bancos de dado nas conexões de Gerenciador de Servidores s. Se o banco de dados que queremos usar não existir na lista suspensa, uma nova conexão de banco de dados poderá ser especificada clicando no botão Nova conexão e fornecendo as informações de conexão necessárias.

a primeira etapa do assistente de configuração do TableAdapter

Figura 1: a primeira etapa do assistente de configuração do TableAdapter (clique para exibir a imagem em tamanho normal)

Vamos reservar um momento para inspecionar o código para a propriedade TableAdapter s Connection. Conforme observado no tutorial criando uma camada de acesso a dados , podemos exibir o código TableAdapter gerado automaticamente acessando a janela modo de exibição de classe, fazendo uma busca detalhada na classe apropriada e clicando duas vezes no nome do membro.

Navegue até a janela de Modo de Exibição de Classe acessando o menu exibir e escolhendo Modo de Exibição de Classe (ou digitando Ctrl + Shift + C). Na parte superior da janela de Modo de Exibição de Classe, faça uma busca detalhada no namespace NorthwindTableAdapters e selecione a classe ProductsTableAdapter. Isso exibirá os membros do ProductsTableAdapter na metade inferior da Modo de Exibição de Classe, como mostra a Figura 2. Clique duas vezes na propriedade Connection para ver seu código.

Clique duas vezes na Propriedade Connection no Modo de Exibição de Classe para exibir seu código gerado automaticamente

Figura 2: clique duas vezes na Propriedade Connection no modo de exibição de classe para exibir seu código gerado automaticamente

A propriedade TableAdapter s Connection e outros códigos relacionados à conexão a seguir:

Private _connection As System.Data.SqlClient.SqlConnection
Private Sub InitConnection()
    Me._connection = New System.Data.SqlClient.SqlConnection
    Me._connection.ConnectionString = _
        ConfigurationManager.ConnectionStrings("NORTHWNDConnectionString").ConnectionString
End Sub
Friend Property Connection() As System.Data.SqlClient.SqlConnection
    Get
        If (Me._connection Is Nothing) Then
            Me.InitConnection
        End If
        Return Me._connection
    End Get
    Set
        Me._connection = value
        If (Not (Me.Adapter.InsertCommand) Is Nothing) Then
            Me.Adapter.InsertCommand.Connection = value
        End If
        If (Not (Me.Adapter.DeleteCommand) Is Nothing) Then
            Me.Adapter.DeleteCommand.Connection = value
        End If
        If (Not (Me.Adapter.UpdateCommand) Is Nothing) Then
            Me.Adapter.UpdateCommand.Connection = value
        End If
        Dim i As Integer = 0
        Do While (i < Me.CommandCollection.Length)
            If (Not (Me.CommandCollection(i)) Is Nothing) Then
                CType(Me.CommandCollection(i), _
                    System.Data.SqlClient.SqlCommand).Connection = value
            End If
            i = (i + 1)
        Loop
    End Set
End Property

Quando a classe do TableAdapter é instanciada, a variável de membro _connection é igual a Nothing. Quando a propriedade Connection é acessada, ela verifica primeiro se a variável de membro _connection foi instanciada. Se não tiver, o método InitConnection será invocado, que instanciará _connection e definirá sua propriedade ConnectionString como o valor da cadeia de conexão especificado na primeira etapa do assistente de configuração do TableAdapter.

A propriedade Connection também pode ser atribuída a um objeto SqlConnection. Isso associa o novo objeto SqlConnection a cada um dos objetos SqlCommand do TableAdapter.

Etapa 2: expondo as configurações de nível de conexão

As informações de conexão devem permanecer encapsuladas no TableAdapter e não podem ser acessadas por outras camadas na arquitetura do aplicativo. No entanto, pode haver cenários em que as informações de nível de conexão do TableAdapter s precisam ser acessíveis ou personalizáveis para uma consulta, usuário ou página ASP.NET.

Deixe que os s estendam o ProductsTableAdapter no conjunto de Northwind para incluir uma propriedade ConnectionString que possa ser usada pela camada de lógica de negócios para ler ou alterar a cadeia de conexão usada pelo TableAdapter.

Note

Uma cadeia de conexão é uma cadeia de caracteres que especifica informações de conexão de banco de dados, como o provedor a ser usado, o local do banco de dados, as credenciais de autenticação e outras configurações relacionadas ao banco de dados. Para obter uma lista dos padrões de cadeia de conexão usados por uma variedade de repositórios de dados e provedores, consulte connectionStrings.com.

Conforme discutido no tutorial criando uma camada de acesso a dados , as classes geradas automaticamente do DataSet s tipadas podem ser estendidas por meio do uso de classes parciais. Primeiro, crie uma nova subpasta no projeto denominada ConnectionAndCommandSettings abaixo da pasta ~/App_Code/DAL.

Adicione uma subpasta chamada ConnectionAndCommandSettings

Figura 3: adicionar uma subpasta chamada ConnectionAndCommandSettings

Adicione um novo arquivo de classe chamado ProductsTableAdapter.ConnectionAndCommandSettings.vb e insira o código a seguir:

Namespace NorthwindTableAdapters
    Partial Public Class ProductsTableAdapter
        Public Property ConnectionString() As String
            Get
                Return Me.Connection.ConnectionString
            End Get
            Set(ByVal value As String)
                Me.Connection.ConnectionString = value
            End Set
        End Property
    End Class
End Namespace

Essa classe parcial adiciona uma propriedade Public chamada ConnectionString à classe ProductsTableAdapter que permite que qualquer camada leia ou atualize a cadeia de conexão para a conexão subjacente do TableAdapter s.

Com essa classe parcial criada (e salva), abra a classe ProductsBLL. Vá para um dos métodos existentes e digite Adapter e, em seguida, pressione a tecla period para abrir o IntelliSense. Você deve ver a nova propriedade ConnectionString disponível no IntelliSense, o que significa que você pode ler ou ajustar programaticamente esse valor da BLL.

Expondo todo o objeto de conexão

Essa classe parcial expõe apenas uma propriedade do objeto de conexão subjacente: ConnectionString. Se desejar disponibilizar todo o objeto de conexão além dos limites do TableAdapter, você poderá alterar o nível de proteção da propriedade de Connection s. O código gerado automaticamente que examinamos na etapa 1 mostrou que a propriedade TableAdapter s Connection está marcada como Friend, o que significa que ele só pode ser acessado por classes no mesmo assembly. No entanto, isso pode ser alterado por meio da propriedade TableAdapter s ConnectionModifier.

Abra o conjunto de Northwind DataSet, clique na ProductsTableAdapter no designer e navegue até a janela Propriedades. Lá, você verá o ConnectionModifier definido com o valor padrão Assembly. Para tornar a propriedade Connection disponível fora do assembly do DataSet tipado, altere a propriedade ConnectionModifier para Public.

o nível de acessibilidade de s da propriedade de conexão pode ser configurado por meio da propriedade ConnectionModifier

Figura 4: o nível de acessibilidade da propriedade Connection s pode ser configurado por meio da propriedade ConnectionModifier (clique para exibir a imagem em tamanho normal)

Salve o conjunto de e retorne à classe ProductsBLL. Como antes, vá para um dos métodos existentes e digite Adapter e, em seguida, pressione a tecla period para abrir o IntelliSense. A lista deve incluir uma propriedade Connection, o que significa que agora você pode ler ou atribuir programaticamente qualquer configuração de nível de conexão da BLL.

Um TableAdapter consiste em uma consulta principal que, por padrão, tem instruções geradas automaticamente INSERT, UPDATEe DELETE. As instruções s INSERT, UPDATEe DELETE da consulta principal são implementadas no código do TableAdapter s como um objeto de adaptador de dados ADO.NET por meio da propriedade Adapter. Assim como com sua propriedade Connection, o tipo de dados da propriedade Adapter s é determinado pelo provedor de dados usado. Como esses tutoriais usam o provedor SqlClient, a propriedade Adapter é do tipo SqlDataAdapter.

A propriedade TableAdapter s Adapter tem três propriedades do tipo SqlCommand que ele usa para emitir as instruções INSERT, UPDATEe DELETE:

  • InsertCommand
  • UpdateCommand
  • DeleteCommand

Um objeto SqlCommand é responsável por enviar uma consulta específica para o banco de dados e tem propriedades como: CommandText, que contém a instrução SQL ad hoc ou o procedimento armazenado a ser executado; e Parameters, que é uma coleção de objetos SqlParameter. Como vimos de volta no tutorial criando uma camada de acesso a dados , esses objetos de comando podem ser personalizados por meio da janela Propriedades.

Além de sua consulta principal, o TableAdapter pode incluir um número variável de métodos que, quando invocados, expedem um comando especificado para o banco de dados. O objeto de comando de consulta principal e os objetos de comando para todos os métodos adicionais são armazenados na propriedade TableAdapter s CommandCollection.

Vamos reservar um momento para examinar o código gerado pelo ProductsTableAdapter no conjunto de Northwind para essas duas propriedades e suas variáveis de membro e métodos auxiliares de suporte:

Private WithEvents _adapter As System.Data.SqlClient.SqlDataAdapter
Private Sub InitAdapter()
    Me._adapter = New System.Data.SqlClient.SqlDataAdapter
    
    ... Code that creates the InsertCommand, UpdateCommand, ...
    ... and DeleteCommand instances - omitted for brevity ...
End Sub
Private ReadOnly Property Adapter() As System.Data.SqlClient.SqlDataAdapter
    Get
        If (Me._adapter Is Nothing) Then
            Me.InitAdapter
        End If
        Return Me._adapter
    End Get
End Property
Private _commandCollection() As System.Data.SqlClient.SqlCommand
Private Sub InitCommandCollection()
    Me._commandCollection = New System.Data.SqlClient.SqlCommand(8) {}
    ... Code that creates the command objects for the main query and the ...
    ... ProductsTableAdapter�s other eight methods - omitted for brevity ...
End Sub
Protected ReadOnly Property CommandCollection() As System.Data.SqlClient.SqlCommand()
    Get
        If (Me._commandCollection Is Nothing) Then
            Me.InitCommandCollection
        End If
        Return Me._commandCollection
    End Get
End Property

O código para as propriedades Adapter e CommandCollection imita de forma muito semelhante a da propriedade Connection. Há variáveis de membro que contêm os objetos usados pelas propriedades. As propriedades Get acessadores começam verificando se a variável de membro correspondente está Nothing. Nesse caso, um método de inicialização é chamado, que cria uma instância da variável de membro e atribui as propriedades principais relacionadas ao comando.

Etapa 4: expondo as configurações de nível de comando

O ideal é que as informações de nível de comando permaneçam encapsuladas na camada de acesso a dados. Caso essas informações sejam necessárias em outras camadas da arquitetura, no entanto, elas podem ser expostas por meio de uma classe parcial, assim como as configurações de nível de conexão.

Como o TableAdapter tem apenas uma única propriedade Connection, o código para expor as configurações de nível de conexão é razoavelmente simples. As coisas são um pouco mais complicadas ao modificar as configurações de nível de comando porque o TableAdapter pode ter vários objetos de comando, um InsertCommand, UpdateCommande DeleteCommand, juntamente com um número variável de objetos Command na propriedade CommandCollection. Ao atualizar as configurações de nível de comando, essas configurações deverão ser propagadas para todos os objetos de comando.

Por exemplo, imagine que havia determinadas consultas no TableAdapter que levaram muito tempo para serem executadas. Ao usar o TableAdapter para executar uma dessas consultas, talvez queiramos aumentar o objeto de comando s CommandTimeout Propriedade. Essa propriedade especifica o número de segundos a aguardar até que o comando seja executado e o padrão é 30.

Para permitir que a propriedade CommandTimeout seja ajustada pela BLL, adicione o seguinte método Public ao ProductsDataTable usando o arquivo de classe parcial criado na etapa 2 (ProductsTableAdapter.ConnectionAndCommandSettings.vb):

Public Sub SetCommandTimeout(ByVal timeout As Integer)
    If Me.Adapter.InsertCommand IsNot Nothing Then
        Me.Adapter.InsertCommand.CommandTimeout = timeout
    End If
    If Me.Adapter.DeleteCommand IsNot Nothing Then
        Me.Adapter.DeleteCommand.CommandTimeout = timeout
    End If
    If Me.Adapter.UpdateCommand IsNot Nothing Then
        Me.Adapter.UpdateCommand.CommandTimeout = timeout
    End If
    For i As Integer = 0 To Me.CommandCollection.Length - 1
        If Me.CommandCollection(i) IsNot Nothing Then
            Me.CommandCollection(i).CommandTimeout = timeout
        End If
    Next
End Sub

Esse método pode ser invocado a partir da camada de apresentação ou BLL para definir o tempo limite do comando para todos os problemas de comandos por essa instância do TableAdapter.

Note

As propriedades Adapter e CommandCollection são marcadas como Private, o que significa que elas só podem ser acessadas a partir do código no TableAdapter. Ao contrário da propriedade Connection, esses modificadores de acesso não são configuráveis. Portanto, se você precisar expor propriedades de nível de comando para outras camadas na arquitetura, deverá usar a abordagem de classe parcial discutida acima para fornecer um método ou propriedade de Public que leia ou grave para os objetos de comando Private.

Resumo

Os TableAdapters em um DataSet tipado servem para encapsular detalhes de acesso a dados e a complexidade. Usando os TableAdapters, não precisamos nos preocupar em escrever o código ADO.NET para se conectar ao banco de dados, emitir um comando ou preencher os resultados em uma DataTable. Tudo é manipulado automaticamente para nós.

No entanto, pode haver ocasiões em que precisamos personalizar as especificidades ADO.NET de baixo nível, como alterar a cadeia de conexão ou os valores padrão de conexão ou tempo limite do comando. O TableAdapter tem propriedades Connection, Adaptere CommandCollection geradas automaticamente, mas elas são Friend ou Private, por padrão. Essas informações internas podem ser expostas estendendo o TableAdapter usando classes parciais para incluir Public métodos ou propriedades. Como alternativa, o modificador de acesso de Propriedade do TableAdapter s Connection pode ser configurado por meio da propriedade TableAdapter s ConnectionModifier.

Boa programação!

Sobre o autor

Scott Mitchell, autor de sete livros sobre ASP/ASP. net e fundador da 4guysfromrolla.com, tem trabalhado com tecnologias Web da Microsoft desde 1998. Scott trabalha como consultor, instrutor e escritor independentes. Seu livro mais recente é que a Sams ensina a ASP.NET 2,0 em 24 horas. Ele pode ser acessado em mitchell@4GuysFromRolla.com. ou por meio de seu blog, que pode ser encontrado em http://ScottOnWriting.NET.

Agradecimentos especiais a

Esta série de tutoriais foi revisada por muitos revisores úteis. Os revisores potenciais para este tutorial foram Burnadette Leigh, S Ren Jacob Lauritsen, Teresa Murphy e Hilton Geisenow. Está interessado em revisar meus artigos futuros do MSDN? Em caso afirmativo, solte-me uma linha em mitchell@4GuysFromRolla.com.