Definir as configurações de nível de conexão e comando da Camada de Acesso a Dados (VB)
por Scott Mitchell
Os TableAdapters em um Conjunto de Dados Tipado cuidam automaticamente da conexão com o banco de dados, da emissão de comandos e do preenchimento de uma DataTable com os resultados. No entanto, há ocasiões em que queremos cuidar desses detalhes e, neste tutorial, aprendemos a acessar as configurações de conexão e nível de comando do banco de dados no TableAdapter.
Introdução
Ao longo da série de tutoriais, usamos Conjuntos de Dados Tipados para implementar a Camada de Acesso a Dados e os objetos de negócios de nossa arquitetura em camadas. Conforme discutido no primeiro tutorial, os DataTables do Conjunto de Dados Tipados servem como repositórios de dados, enquanto os TableAdapters atuam como wrappers para se comunicar com o banco de dados para recuperar e modificar os dados subjacentes. Os TableAdapters encapsulam a complexidade envolvida no trabalho com o banco de dados e nos evitam de ter que escrever código para se conectar ao banco de dados, emitir um comando ou preencher os resultados em uma DataTable.
Há momentos, no entanto, em que precisamos nos aprofundar no TableAdapter e escrever código que funciona diretamente com os objetos ADO.NET. No tutorial Encapsulando modificações de banco de dados em uma transação , por exemplo, adicionamos métodos ao TableAdapter para iniciar, confirmar e reverter ADO.NET transações. Esses métodos usaram um objeto interno criado SqlTransaction
manualmente que foi atribuído aos objetos de SqlCommand
TableAdapter.
Neste tutorial, examinaremos como acessar as configurações de conexão e nível de comando do banco de dados no TableAdapter. Em particular, adicionaremos funcionalidade ao que permite o ProductsTableAdapter
acesso às configurações subjacentes de cadeia de conexão e tempo limite de 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 System.Data
namespace , são chamadas de classes ADO.NET . Algumas das classes sob a ADO.NET guarda-chuva estão vinculadas a um provedor de dados específico. Você pode pensar em 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 especialmente projetados para um sistema de banco de dados específico. Por exemplo, embora seja possível se conectar a um banco de dados do 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 seguinte padrão é comumente usado:
- Estabeleça uma conexão com o banco de dados.
- Emita um comando.
- 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 SqlConnection
classe . Para emitir um INSERT
comando , UPDATE
, DELETE
ou SELECT
para o banco de dados, use a SqlCommand
classe .
Exceto para o tutorial Encapsulando modificações de banco de dados em um tutorial de transação , não tivemos que escrever nenhum código de ADO.NET de baixo nível porque o código gerado automaticamente tableAdapters inclui a funcionalidade necessária para se conectar ao banco de dados, emitir comandos, recuperar dados e preencher esses dados em DataTables. No entanto, pode haver momentos em que precisamos personalizar essas configurações de baixo nível. 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 Connection
propriedade que especifica informações de conexão de banco de dados. O tipo de dados e ConnectionString
o valor dessa propriedade são determinados pelas seleções feitas no assistente de Configuração do TableAdapter. Lembre-se de que, quando adicionamos pela primeira vez um TableAdapter a um Conjunto de Dados Tipado, esse assistente nos solicita a origem do banco de dados (consulte a Figura 1). A lista suspensa nesta primeira etapa inclui os bancos de dados especificados no arquivo de configuração, bem como quaisquer outros bancos de dados no Connections de Dados do Explorer Do Servidor. Se o banco de dados que desejamos 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.
Figura 1: a primeira etapa do Assistente de Configuração do TableAdapter (clique para exibir a imagem em tamanho real)
Vamos demorar um pouco 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 Exibição de Classe, fazendo drill down até a classe apropriada e clicando duas vezes no nome do membro.
Navegue até a janela Modo de Exibição de Classe acessando o menu Exibir e escolhendo Modo de Exibição de Classe (ou digitando Ctrl+Shift+C). Na metade superior da janela Exibição de Classe, faça drill down até o NorthwindTableAdapters
namespace e selecione a ProductsTableAdapter
classe . Isso exibirá os ProductsTableAdapter
membros s na metade inferior do Modo de Exibição de Classe, conforme mostrado na Figura 2. Clique duas vezes na Connection
propriedade para ver seu código.
Figura 2: Double-Click a propriedade Connection na exibição de classe para exibir seu código gerado automaticamente
A propriedade TableAdapter s Connection
e outro código relacionado à conexão seguem:
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 TableAdapter é instanciada, a variável _connection
de membro é igual a Nothing
. Quando a Connection
propriedade é acessada, ela primeiro verifica se a _connection
variável de membro foi instanciada. Se não tiver, o InitConnection
método será invocado, o que cria uma instância _connection
e define sua ConnectionString
propriedade como o valor de cadeia de conexão especificado na primeira etapa do assistente de Configuração do TableAdapter.
A Connection
propriedade também pode ser atribuída a um SqlConnection
objeto . Isso associa o novo SqlConnection
objeto a cada um dos objetos tableAdapter.SqlCommand
Etapa 2: Expondo configurações de Connection-Level
As informações de conexão devem permanecer encapsuladas no TableAdapter e não estar acessíveis a outras camadas na arquitetura do aplicativo. No entanto, pode haver cenários em que as informações no nível de conexão do TableAdapter precisam ser acessíveis ou personalizáveis para uma consulta, um usuário ou uma página de ASP.NET.
Vamos estender o ProductsTableAdapter
no Northwind
DataSet para incluir uma ConnectionString
propriedade que pode ser usada pela Camada de Lógica de Negócios para ler ou alterar o cadeia de conexão usado pelo TableAdapter.
Observação
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 de padrões de cadeia de conexão usados por uma variedade de armazenamentos de dados e provedores, consulte ConnectionStrings.com.
Conforme discutido no tutorial Criando uma camada de acesso a dados , as classes geradas automaticamente do Conjunto de Dados Tipados podem ser estendidas por meio do uso de classes parciais. Primeiro, crie uma nova subpasta no projeto denominada ConnectionAndCommandSettings
abaixo da ~/App_Code/DAL
pasta .
Figura 3: Adicionar uma subpasta chamada ConnectionAndCommandSettings
Adicione um novo arquivo de classe chamado ProductsTableAdapter.ConnectionAndCommandSettings.vb
e insira o seguinte código:
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 Public
propriedade chamada ConnectionString
à ProductsTableAdapter
classe que permite que qualquer camada leia ou atualize o cadeia de conexão para a conexão subjacente do TableAdapter.
Com essa classe parcial criada (e salva), abra a ProductsBLL
classe . Vá para um dos métodos existentes e digite e, em Adapter
seguida, pressione a chave de ponto para abrir o IntelliSense. Você deve ver a nova ConnectionString
propriedade disponível no IntelliSense, o que significa que você pode ler ou ajustar programaticamente esse valor da BLL.
Expondo todo o objeto Connection
Essa classe parcial expõe apenas uma propriedade do objeto de conexão subjacente: ConnectionString
. Se você quiser disponibilizar todo o objeto de conexão além dos limites do TableAdapter, como alternativa, poderá alterar o Connection
nível de proteção da propriedade. 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 ela só pode ser acessada por classes no mesmo assembly. No entanto, isso pode ser alterado por meio da propriedade TableAdapter s ConnectionModifier
.
Abra o Northwind
DataSet, clique no ProductsTableAdapter
na Designer e navegue até o janela Propriedades. Lá, você verá o ConnectionModifier
definido como seu valor padrão, Assembly
. Para disponibilizar a Connection
propriedade fora do assembly do Conjunto de Dados Tipado, altere a ConnectionModifier
propriedade para Public
.
Figura 4: o Connection
nível de acessibilidade da propriedade pode ser configurado por meio da ConnectionModifier
propriedade (clique para exibir a imagem em tamanho real)
Salve o DataSet e retorne à ProductsBLL
classe . Como antes, vá para um dos métodos existentes e digite e, em Adapter
seguida, pressione a chave de ponto para abrir o IntelliSense. A lista deve incluir uma Connection
propriedade , o que significa que agora você pode ler ou atribuir programaticamente as configurações de nível de conexão da BLL.
Etapa 3: Examinando as propriedades do Command-Related
Um TableAdapter consiste em uma consulta main que, por padrão, tem instruções , UPDATE
e DELETE
geradas INSERT
automaticamente. Essa main as instruções , INSERT
UPDATE
e DELETE
são implementadas no código do TableAdapter como um objeto do adaptador de dados ADO.NET por meio da Adapter
propriedade . Assim como acontece com sua Connection
propriedade, o Adapter
tipo de dados da propriedade é determinado pelo provedor de dados usado. Como esses tutoriais usam o provedor SqlClient, a Adapter
propriedade é do tipo SqlDataAdapter
.
A propriedade TableAdapter s Adapter
tem três propriedades do tipo SqlCommand
que usa para emitir as INSERT
instruções , UPDATE
e DELETE
:
InsertCommand
UpdateCommand
DeleteCommand
Um SqlCommand
objeto é 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 SqlParameter
objetos . Como vimos no tutorial Criando uma camada de acesso a dados, esses objetos de comando podem ser personalizados por meio do janela Propriedades.
Além de sua consulta main, o TableAdapter pode incluir um número variável de métodos que, quando invocados, despacham um comando especificado para o banco de dados. O objeto de comando da consulta main e os objetos de comando para todos os métodos adicionais são armazenados na propriedade TableAdapter sCommandCollection
.
Vamos dar uma olhada no código gerado pelo ProductsTableAdapter
no Northwind
DataSet para essas duas propriedades e suas variáveis de membro de suporte e métodos auxiliares:
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 Adapter
propriedades e CommandCollection
imita de perto o Connection
da propriedade . Há variáveis de membro que contêm os objetos usados pelas propriedades. Os acessadores de propriedades Get
começam verificando se a variável de membro correspondente é Nothing
. Nesse caso, um método de inicialização é chamado, o que cria uma instância da variável de membro e atribui as propriedades principais relacionadas ao comando.
Etapa 4: Expondo configurações de Command-Level
Idealmente, as informações de nível de comando devem permanecer encapsuladas dentro da Camada de Acesso a Dados. No entanto, se essas informações forem necessárias em outras camadas da arquitetura, elas poderão ser expostas por meio de uma classe parcial, assim como nas configurações de nível de conexão.
Como o TableAdapter tem apenas uma única Connection
propriedade, o código para expor as configurações de nível de conexão é bastante 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
, UpdateCommand
e DeleteCommand
, juntamente com um número variável de objetos de comando na CommandCollection
propriedade . Ao atualizar as configurações de nível de comando, essas configurações precisarão ser propagadas para todos os objetos de comando.
Por exemplo, imagine que havia certas consultas no TableAdapter que levaram muito tempo para serem executadas. Ao usar o TableAdapter para executar uma dessas consultas, talvez queiramos aumentar a propriedade do objeto de comando.CommandTimeout
Essa propriedade especifica o número de segundos a aguardar a execução do comando e o padrão é 30.
Para permitir que a CommandTimeout
propriedade seja ajustada pela BLL, adicione o seguinte Public
método 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 da BLL ou camada de apresentação para definir o tempo limite do comando para todos os problemas de comandos por essa instância tableAdapter.
Observação
As Adapter
propriedades e CommandCollection
são marcadas como Private
, o que significa que elas só podem ser acessadas do código dentro do TableAdapter. Ao contrário da Connection
propriedade , esses modificadores de acesso não são configuráveis. Portanto, se você precisar expor propriedades de nível de comando a outras camadas na arquitetura, deverá usar a abordagem de classe parcial discutida acima para fornecer um Public
método ou propriedade que lê ou grava nos objetos de Private
comando.
Resumo
Os TableAdapters em um Conjunto de Dados Tipado servem para encapsular detalhes e complexidade de acesso a dados. Usando TableAdapters, não precisamos nos preocupar em escrever ADO.NET código para se conectar ao banco de dados, emitir um comando ou preencher os resultados em uma DataTable. Tudo é tratado automaticamente para nós.
No entanto, pode haver momentos em que precisamos personalizar as especificações de ADO.NET de nível inferior, como alterar o cadeia de conexão ou os valores padrão de tempo limite de conexão ou comando. O TableAdapter tem propriedades , Adapter
e geradas Connection
automaticamente, mas elas são Friend
ou Private
, CommandCollection
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 à propriedade TableAdapter Connection
pode ser configurado por meio da propriedade TableAdapter s ConnectionModifier
.
Programação feliz!
Sobre o autor
Scott Mitchell, autor de sete livros do ASP/ASP.NET e fundador da 4GuysFromRolla.com, trabalha com tecnologias da Microsoft Web desde 1998. Scott trabalha como consultor independente, treinador e escritor. Seu último livro é Sams Teach Yourself ASP.NET 2.0 em 24 Horas. Ele pode ser contatado em mitchell@4GuysFromRolla.com. ou através de seu blog, que pode ser encontrado em http://ScottOnWriting.NET.
Agradecimentos Especiais
Esta série de tutoriais foi revisada por muitos revisores úteis. Os principais revisores deste tutorial foram Burnadette Leigh, S ren Jacob Lauritsen, Teresa Murphy e Hilton Geisenow. Interessado em revisar meus próximos artigos do MSDN? Nesse caso, deixe-me uma linha em mitchell@4GuysFromRolla.com.