VB .NET - Camada de dados e TableAdapters em WIndows Forms
Se você digitar as palavras DAL(Data Access layer) no Google vai encontrar centenas de referências. Há uns 5 anos atrás este tema estava quase que restrito uns poucos 'esclarecidos' que já vislumbravam os benefícios de se trabalhar em camadas.
Nota: Veja também meu artigo sobre o assunto usando ASP.NET - ASP.NET 2.0 - Criando uma camada de acesso a dados.
Considero isso um bom sinal , afinal estamos todos evoluindo e procurando criar softwares de qualidade, com desempenho e de fácil manutenção. Um dia vamos chegar lá... (foi um piada...)
Bem, o meu assunto hoje aqui é mostrar como você, sim você mesmo, pode criar sua própria camada de acesso a dados ( a famosa DAL) usando o Visual Basic 2005 Express Edition e os seus novos recursos em aplicações Windows(leia-se TableAdapters).
O que é uma
Camada de Acesso a Dados ? É uma camada separada da camada da apresentação de dados que tem a função de efetuar a conexão com a fonte de dados e através de comandos SQL (neste nosso caso) obter os dados para apresentação. Esta separação facilita a manutenção e a portabilidade da aplicação. A camada de apresentação, quando deseja exibir algum dado, chama a camada de de negócios (ausente neste artigo) que chama a camada de acesso aos dados e solicita a informação. A camada de apresentação não acessa dados nem a camada de dados faz apresentação. Cada uma cumpre o seu papel. |
Obs: A camada de negócios não esta sendo criada por uma questão de simplificação e para facilitar o entendimento.
Em uma aplicação construída em camadas geralmente temos :
1- A camada de apresentação - Que é responsável por apresentar o resultado do processamento. Esta camada deve ser o menos dependente possível das demais camadas de forma que a sua manutenção não exija o conhecimento da lógica de negócio nem da camada de dados;
2- A camada da lógica de negócio - Responsável pelas regras e processos de negócio da sua aplicação.
3- A camada de dados - Representam os dados da sua aplicação. Ela pode ser dividida em:
Com isto em mente devemos ter:
Temos a seguir uma figura representando as camadas e a DAL(Data Access Layer) que iremos criar:
Este artigo usará como exemplo um banco de dados criado no SQL Server 2005 Express. O banco de dados Cadastro.mdf e a tabela Clientes cuja estrutura é a seguinte :
Para saber como criar novos arquivos no SQL Server 2005 Express veja o artigo : .NET 2005 - Usando o SQL Server Management Studio
Exibindo a propriedades do banco de dados:
Um
banco de dados local pode ser incluído como um arquivo no seu projeto. A
primeira vez que você efetuar uma conexão com sua aplicação ao arquivo de
banco de dados local você escolherá entre criar uma copia do banco de dados
no seu projeto ou conectar-se ao banco de dados existente na sua localização
original. Se você escolher que deseja se conectar com o banco de dados existente , então a conexão é criada como se você estivesse se conectando a qualquer banco de dados remoto e o arquivo de banco de dados será deixado na sua localização original. Se você escolher copiar o banco de dados para o seu projeto , o VB 2005 ou VS cria uma cópia do arquivo, e o inclui no seu projeto modificando a conexão de forma que ela agora aponta para o banco de dados no seu projeto. Por padrão quando você constrói um
projeto , o banco de dados é copiado da pasta raiz do projeto para a pasta
de saida (bin). (Selecione Show All Files para ver a pasta bin) O arquivo de banco de dados na pasta raiz do seu projeto somente será alterado quando você editar o esquema ou os dados do banco de dados usando o Server Explorer/DataBase Explorer ou outra ferramenta Visual. O relacionamento entre as duas versões do seu banco de dados é dependente da forma como você define a propriedade Copy to Output Directory. Durante o desenvolvimento da aplicação, qualquer alteração feita nos dados (durante o tempo que você roda a sua aplicação) são feitas também no banco de dados da pasta bin. Assim por exemplo se você rodar a sua aplicação pressionando F5 você estará se conectando com o banco de dados na pasta bin. Se você deixar a propriedade definida com o valor 'Copy always' uma nova cópia do banco de dados será copiada para a pasta bin cada vez que você executar sua aplicação e desta forma você não verá as alterações feitas no banco de dados e os dados parecerão que não estão sendo atualizados. |
1- Criando um DataSet tipado e um TableAdapter
Como vemos na figura acima nossa proposta é criar uma camada de acesso a dados usando TableAdapter e DataTable de forma que todo o código de acesso aos dados esteja na DAL.
Inicie um novo projeto no Visual Basic 2005 Express Edition do tipo Windows Application com o nome de DALWindowsNet;
Clique com o botão direito do mouse sobre o nome do projeto e selecione a opção Add -> Add New Item
Na janela Add New Item selecione DataSet e informe o nome Cadastro.xsd
Um DataSet Tipado funciona como uma coleção fortemente tipada de dados e é composto de instâncias de DataTables fortemente tipadas onde cada uma é composta de instâncias de DataRow fortemente tipadas. |
A seguir selecione o DataSet criado e abra a ToolBox. Na ToolBox arraste e solte o objeto tableAdapter para o formulário:
Ao fazer isto o assistente para criação de TableAdapter irá surgir. Selecione a conexão com a base Cadastro.mdf e clique em Next>;
Na próxima etapa salve a string de conexão e clique em Next>;
A seguir vamos definir o esquema
do Datatable fortemente tipado e fornecer o primeiro método para acessar os
dados via TableAdapter usado para preencher o DataSet tipado. Para iniciar vamos definir a consulta SQL que deve indicar como queremos que o TableAdapter trate a consulta. Clique no botão Next>
|
Podemos definir a consulta SQL
digitando diretamente ou usando o Assistente construtor - Query Builder
para montar o seu SQL e ver o resultado. Vamos incluir um comando SELECT que retorne algumas das colunas da tabela Clientes. SELECT Codigo, Nome, Endereco, Renda FROM Clientes A seguir clique no botão Next> |
Depois de criar a consulta clique no botão Advanced Options e serão exibidas as opções já marcadas pois estamos em uma aplicação Windows Forms. Se estivéssemos em um projeto Web somente a primeira opção seria marcada por padrão.
Existe uma
diferença básica entre as aplicações Windows e as aplicações Web:
As aplicações web geralmente atualizam registros individualmente enquanto que as aplicações Windows atualizam blocos de registros usando um DataSet.(Veja abaixo sobre os dois modelos de atualização usados pelo TableAdapter)(*) O TableAdapter possui diferentes formas de atualização, prevendo justamente este comportamento diferente. Assim, em aplicações web ele pode usar os DbDirectMethods e em aplicações Windows ele gera métodos de atualização que usam parâmetros recebidos (DataTable e DataSet) e atualizam todos os dados. |
Na fase final temos dois padrões
para preencher os dados: - Fill a DataTable - cria um método que usa um DataTable como parâmetro e preenche-o baseado no resultado da consulta - Return DataTable - cria e preenche o DataTable e retorna como o retorno do método. Podemos e vamos usar ambos deixando as caixas de opção marcadas. Vamos alterar o método GetData para Get. Se marcarmos a última caixa de opção - , GenerateDBDirectMethods , serão criados os métodos : Insert(), Update() e Delete() para o TableAdapter. Se a caixa for desmarcada todas as atualizações deverão ser feitas através do método Update() do TableAdapter.(*) Finalmente clique no botão FInish. (Finalmente...) |
Neste momento já temos o DataSet tipado contendo o DataTable (Cadastro.Clientes) e a classe DataAdapter (CadastroTableAdapters.ClientesTableAdapter) cujo método getClientes pode ser usado para obtermos os dados da tabela clientes e exibir na camada de apresentação. |
Vamos usar o recurso na nossa aplicação Windows. Inclua no formulário padrão form1.vb um controle ListBox , um DataGridView e um botão de comando conforme figura abaixo:
Inclua o seguinte código no evento
Click do botão de comando:
|
Executando o projeto iremos obter:
Conferindo o código acima vemos
que realmente não escrevemos uma linha de código para acesso específico a
dados. Não precisamos instanciar classes ado.net nem fazer referência a
strings de conexão, consultas SQL ou procedimentos armazenados. O responsável por todo o serviço foi o TableAdapter que fez o papel da nossa DAL.
|
2- Criando uma consulta parametrizada
Vamos agora estender um pouco as funcionalidades da nossa DAL incluindo um novo método no TableAdapter. Vamos incluir um método contendo um parâmetro de forma a poder selecionar um determinado cliente pelo seu Código - getClientesByCodigo(Codigo).
Volte a selecionar o DataSet e clique com o botão direito do mouse sobre a seção ClientesTableAdapter selecionando em seguida Add Query:
Como queremos obter todos os
clientes para um determinado código iremos usar um SELECT que retorna
linhas. A seguir clique em Next> |
Você pode montar a instrução SQL para obter os clientes pelo código usando o Query Builder ou digitando diretamente. Veja abaixo a instrução SQL criada.
No passo final podemos informar o nome dos métodos gerados conforme figura abaixo:
Após clicar no botão Finish se voltarmos ao nosso TableAdapter veremos os novos métodos gerados. |
Vamos agora por o recurso para funcionar em nossa aplicação Windows, insira no formulário um controle ComboBox e uma Label conforme figura abaixo:
Para que os valores dos códigos
sejam preenchidos pela combobox podemos selecionar o controle e na
propriedade DataSource atribuir a tabela clientes conforme figura ao
lado. Após isso basta definir a propriedade DisplayMember como sendo o codigo. |
Agora para obter os clientes quando um código for selecionado na combobox inclua o seguinte código no evento SelectedIndexChanged :
Private
Sub cboCodigo_SelectedIndexChanged(ByVal
sender As System.Object,
ByVal e As System.EventArgs)
Handles cboCodigo.SelectedIndexChanged If cboCodigo.Text = String.Empty Then Exit Sub clientes = clientesAdapter.GetClientesByCodigo(CType(cboCodigo.Text, Integer)) dgvClientes.DataSource = clientes End Sub |
Executando o projeto teremos:
3- Incluindo , Excluindo e atualizando dados
Existem dois modelos usados para inserir , atualizar e deletar dados. O primeiro usa o modelo de acesso direto ao banco de dados e envolve a criação de métodos que quando invocados aplicam um comando INSERT, UPDATE e DELETE no banco de dados e que atuam em um único registro. Estes métodos são passados usando valores escalares (inteiros, strings, booleanos, etc.). Assim para excluir o cliente com código igual a 1 o método DELETE é passado com o parâmetro inteiro 1.(*)
Modelo de atualização por registro | Modelo de atualização em lote |
O TableAdapter usa por padrão a atualização em lote mas suporta também o modelo de acesso direto. No momento em que nós selecionamos a opção "Generate Insert, Update, and Delete statements" a partir da opção Options Advanced quando da geração do TableAdapter pelo Assistente, ele passou a conter o método Update() que implementa o modelo de atualização em lote.( Especificamente o TableAdapter contém o método Update() que pode passar o DataSet tipado, um DataTable tipado ou mais de um DataRows.) Neste momento se você deixar marcado a opção "GenerateDBDirectMethods" os métodos insert(), update() e delete() também serão criados.
Ambos os modelos de atualização utilizam as propriedades InsertCommand, UpdateCommand, e DeleteCommand do TableAdapter para aplicar os comandos INSERT, UPDATE e DELETE ao banco de dados. Você pode dar uma olhada nestas propriedades na janela de propriedades e pode também alterá-las selecionando a propriedade CommandText e clicando no botão a direita para abrir a janela Query Builder.
As propriedades InsertCommand, UpdateCommand, e DeleteCommand
do TableAdpater
|
Para usar os métodos de atualização individuais gerados por GenerateDBDirectMethods basta invocar o método com o parâmetro apropriado. Para a nossa tabela clientes e para o nosso TableAdapter podemos ter:
Dim clientesAdapter
As New
CadastroTableAdapters.ClientesTableAdapter
' Deleta o cliente com código
igual a 1 ' Atualiza o endereco cliente
de codigo 1 ' Inclui um novo cliente |
Para atualizar a atualização em lote, como exemplo podemos usar o seguinte trecho de código que atualiza a renda dos clientes com código superior a 2;
Dim clientesAdapter As
New CadastroTableAdapters.ClientesTableAdapter
Dim clientes As
Cadastro.ClientesDataTable = clientesAdapter.GetClientes 'atualiza a renda dos clientes com codigo superior a 2 For Each cliente As Cadastro.ClientesRow In clientesIf Not cliente.Codigo > 2 Then cliente.Renda += 10 End If Next
clientesAdapter.Update(clientes) |
Obs: Estes métodos poderiam ser chamados a partir de eventos de botões ou de rotinas de sua aplicação Windows.
4- Personalizando as inclusões , exclusões e atualizações
Se você der uma espiada nos métodos insert(), update() e delete() de acesso direto aos dados criados no TableAdapter pelo assistente vai notar que eles são complexos, principalmente para tabelas com muitas colunas. Será que não podemos gerar os nosso próprios métodos para realizar tais tarefas de uma maneira mais simples ?
Sim, podemos usar o assistente para incluir métodos que realizam tais operações. Vamos criar um novo método para incluir um novo registro na nossa tabela Clientes.
Para fazer isto clique com o botão direito do mouse sobre o TableAdapter e selecione a opção Add Query e a seguir na janela do assistente selecione a opção Use SQL Statements
A seguir clique em Next> |
Na próxima janela - Choose a Query Type - selecione a opção - INSERT ( adds a new row to a table) e clique no botão Next>
A próxima tela exibre o comandText insertCommand que inclui um novo registro na tabela clientes. Ajuste a instrução exibida com a cláusula SELECT SCOPE IDENTITY com isto estaremos retornando o último valor do código (IDENTITY) incluído na tabela.
No SQL Server após você realizar uma operação de inclusão de dados via INSERT , SELECT INTO ou uma cópia em massa (BULKY COPY) em uma tabela com uma coluna IDENTITY, a variável global @@IDENTITY conterá o último valor da identidade que é gerado pela instrução. (Se nenhuma coluna for sensibilidade será retornado NULL). Se múltiplas linhas tiverem sido incluídas , gerando múltiplos valores identidade(IDENTITY) o último será retornado. Para obter o último valor identidade gerado nestes casos podemos usar as funções @@IDENTITY, SCOPE_IDENTITY, e IDENT_CURRENT.
IDENT_CURRENT - Retorna o último valor identidade gerado para uma
tabela específica em qualquer sessão e em qualquer escopo.
SCOPE_IDENTITY - Retorna o último
valor identidade gerado para qualquer tabela na sessão atual e no escopo
atual. |
Clique em Next> e informe o nome da função a ser gerada como sendo : incluirCliente.
Na etapa final você verá a tela de resultado do assistente conforme a abaixo e após clicar no botão Finish verá o TableAdapter exibindo o novo método - incluirCliente :
Como último ajuste você pode alterar a propriedade ExecuteMode da Query criada. O padrão é NonQuery que retorna o valor das linhas afetadas pela execução da query. Para retornar o valor da consulta altere para Scalar.
Para usar o novo recurso inclua um novo formulário através do menu Project -> Add Windows Forms . Será incluído o formulário form2.vb no projeto.
Insira o formulário 3 Labels e 3 caixas de Textos dois controles Button conforme figura abaixo:
Agora inclua o seguinte código no formulário:
Dim clientesAdapter As
CadastroTableAdapters.ClientesTableAdapter = New
CadastroTableAdapters.ClientesTableAdapter Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Me.Close()
End
Sub Try clientesAdapter.incluirCliente(txtNome.Text, txtEndereco.Text, CType(txtRenda.Text, Decimal)) MsgBox("Registro incluido com sucesso") Catch ex As Exception MsgBox(ex.Message) End Try End Sub |
Pronto ! com poucas linhas de código acabamos de usar novo método inserirCliente para incluir um novo registro na base de dados.
Nota: Para tornar o exemplo bem simples não efetuei a validação dos dados.
Encerro aqui esta pequena introdução a criação de uma camada de acesso a dados (DAL) usando TableAdapter para aplicações WIndows Forms.
Se você percebeu a tarefa não exige grandes conhecimentos nem é muito trabalhosa. Podemos aprofundar mais o assunto mostrando como criar regras de negócio e efetuar a sua integração entre as camadas e também com estender a funcionalidade do TableAdapter.
Mas isto é assunto para outro artigo. Até lá...
Pegue o projeto exemplo aqui : DALNet.zip
Veja os
Destaques e novidades do SUPER DVD Visual Basic
(sempre atualizado) : clique e confira !
Quer migrar para o VB .NET ?
Quer aprender C# ??
Quer aprender os conceitos da Programação Orientada a objetos ? Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ? |
Referências:
Super DVD Vídeo Aulas - Vídeo Aula sobre VB .NET, ASP .NET e C#
Super DVD C# - Recursos de aprendizagens e vídeo aulas para C#
Curso Fundamentos da Programação Orientada a Objetos com VB .NET
how create tableadapters : http://msdn2.microsoft.com/en-gb/library/6sb6kb28(VS.80).aspx
Tutorial - Create a DAL - http://msdn2.microsoft.com/en-us/library/aa581778.aspx#aspnet_tutorial01_dataaccesslayer_vb_topic3