VB
.NET - Acessando um banco de dados Access (CRUD) - II
Na primeira parte deste artigo eu crie uma aplicação VB .NET para realizar a manutenção em uma tabela Alunos do banco de dados Escola.mdb.
Assim criamos o banco de dados Escola.mdb e a tabela Alunos e a seguir criamos o projeto no VB .NET 2010 Express onde definimos as operações para incluir, alterar, excluir e consultar registros na tabela Alunos.
Concluímos e testamos o projeto e esta tudo funcionando sem problemas.
O que vamos então fazer neste artigo ?
Embora nossa aplicação esteja funcional ele pode ser melhorada para ser mais fácil de manter e de estender.
Como assim ???

Quando criamos nossa aplicação definimos na camada de apresentação, no caso o formulário form1.vb, todas as operações nos eventos dos botões de comando.
![]() |
Assim usamos o código para acessar e para apresentar os dados em um único lugar: a camada de apresentação.
Se você analisar o código usado irá notar que usamos referências aos namespaces System.Data e System.Data.Oledb no formulário e que no código usado criamos instâncias de objetos ADO .NET como Connection, Command, DataTable, DataAdatper também no formulário. Além disso definimos os comandos SQL para selecionar, incluir, alterar e excluir também no formulário.
Temos também código duplicado no formulário, principalmente na definição da string de conexão, que esta sendo definida em cada evento Click dos botões Novo,Deletar, Alterar e Procurar.
Dessa forma nosso formulário além de código duplicado também possui mesclado o código de apresentação e o código de acesso a dados e isso não é uma boa prática.
Por quê ? ![]()
Porque qualquer alteração relacionada com o acesso aos dados implicará em alterar também a camada de apresentação. A criação de um novo campo, por exemplo, faria com que o formulário form1.vb fosse todo alterado pois nele esta contido toda a lógica de acesso aos dados.
Se a string e conexão for alterada também teremos que alterar o código em todo o formulário.
Vamos então separar as responsabilidades e remover do formulário todo o código e referência relacionada com o acesso aos dados criando uma camada de acesso a dados que será responsável conhecer, acessar, e retornar as informações dos dados.
Nosso formulário form1.vb deverá unicamente chamar a camada de acesso a dados e apresentar o resultado ao usuário.
Além disso vamos definir a string de conexão em um único lugar na aplicação que será o arquivo de configuração App.Config. Para obter a string de conexão iremos acessar e recuperar a string de conexão deste arquivo. Assim se houver qualquer mudança na string de conexão teremos que alterar somente em único local o seu valor.
Criando a infraestrutura da camada de acesso aos dados
Abra o projeto original CadastroAlunosAccess onde teremos apenas o formulário form1.vb. Vamos criar a infraestrutura para podermos criar a nossa camada de acesso aos dados
1- Referenciando o namespace System.Configuration
No menu Project, clique em Add Reference e na janela Add Reference clique na guia .NET e selecione System.Configuration e clique em OK;
![]() |
2- Criando o arquivo de configuração App.Config
No menu Project clique em Add New Item e selecione o template Application Configuration FIle aceitando o nome padrão app.config e clique em Add;
![]() |
3- Definindo a string e conexão no arquivo app.config
Abra o arquivo app.config criado e inclua o código destacado em azul abaixo neste arquivo:
| <?xml version="1.0"?> <configuration> <connectionStrings> <add name="ConexaoEscolaMDB" providerName="System.Data.OleDb" connectionString="Provider=Microsoft.Jet.OleDb.4.0; Data Source=C:\dados\Escola.mdb"/> </connectionStrings> <system.diagnostics> ........ |
Definimos no arquivo a string de conexão com o banco de dados identificada pelo nome ConexaoEscolaMDB.
4- Criando a classe Aluno
No menu Project, Clique em Add Class, informe o nome Aluno.vb e clique no botão Add;
A seguir defina o código abaixo na classe Aluno:
| Public
Class
Aluno Public Property Codigo As Integer Public Property Nome As String Public Property Imagem As Image End Class |
A classe Aluno representa um aluno e possui 3 propriedades que possuem nomes idênticos aos campos da tabela Alunos.
Usamos essa classe para realizar a comunicação entre as camadas de acesso a dados e a camada de apresentação. Podemos dizer que essa classe é um DTO - Data Transfer Object.
Criando a camada de apresentação
Volte ao menu Project, clique em Add Class e informe o nome AcessoDados.vb clicando a seguir no botão Add para criar a classe AcessoDados;
Defina os seguintes namespaces neste arquivo:
Imports
System.DataE a seguir, logo após a declaração da classe vamos definir os objetos ADO .NET:
Dim Da As New OleDbDataAdapterAgora podemos iniciar a criação dos métodos da classe AcessoDados que irão acessar e persistir os dados na tabela Alunos.
1- Método getConexaoDB() - obtém a string de conexão do arquivo app.config, abre e retorna uma conexão do tipo OledbConnection;
Public Function getConexaoDB() As OleDbConnection
Try
cn.ConnectionString = ConfigurationManager.ConnectionStrings("ConexaoEscolaMDB").ConnectionString
cn.Open()
Return cn
Catch ex As Exception
Throw ex
End Try
End Function
|
2- Método closeConexaoDB() - Fecha uma conexão aberta
Public Sub closeConexaoDB(ByVal cn As OleDbConnection)
Try
If cn.State = ConnectionState.Open Then
cn.Close()
End If
Catch ex As Exception
Throw ex
End Try
End Sub
|
3- Método incluirDados() - Inclui um novo aluno na tabela alunos usando o comando SQL INSERT INTO;
Public Sub incluirDados(ByVal nome As String, ByVal arrImage() As Byte, ByVal strImage As String)
Try
cn = getConexaoDB()
Cmd.Connection = cn
Cmd.CommandText = "INSERT INTO Alunos(nome, imagem) " & _
"VALUES( '" & nome & "'," & strImage & ")"
If strImage = "?" Then
Cmd.Parameters.Add(strImage, OleDb.OleDbType.Binary).Value = arrImage
End If
Cmd.ExecuteNonQuery()
Catch ex As Exception
Throw ex
Finally
closeConexaoDB(cn)
End Try
End Sub
|
4- Método procurarDados() - seleciona um aluno pelo código e retorna um objeto Aluno.
Public Function procurarDados(ByVal codigo As Integer) As Aluno Dim aluno As New Aluno Try
cn = getConexaoDB()
Dim da As New OleDb.OleDbDataAdapter("SELECT * FROM Alunos " & " WHERE codigo=" & codigo, cn)
Dim dt As New DataTable
Dim arrImage() As Byte = Nothing
Dim myMS As New IO.MemoryStream
da.Fill(dt) If dt.Rows.Count > 0 Then
aluno.Codigo = dt.Rows(0).Item("codigo")
aluno.Nome = dt.Rows(0).Item("nome") & ""
If Not IsDBNull(dt.Rows(0).Item("imagem")) Then
arrImage = dt.Rows(0).Item("imagem")
For Each ar As Byte In arrImage
myMS.WriteByte(ar)
Next
aluno.Imagem = System.Drawing.Image.FromStream(myMS)
Else
aluno.Imagem = Nothing
End If
Else
aluno = Nothing
End If
Catch ex As Exception
Throw ex
Finally
closeConexaoDB(cn)
End Try
Return Aluno
End Function |
5- Método carregaDados() - Seleciona todos os alunos e retorna um DataTable.
Public Function carregaDados() As DataTable
Dt = New DataTable
cn = getConexaoDB()
Try
With Cmd
.CommandType = CommandType.Text
.CommandText = "SELECT * from Alunos"
.Connection = cn
End With
With Da
.SelectCommand = Cmd
.Fill(Dt)
End With
Catch ex As Exception
Dt = Nothing
Finally
closeConexaoDB(cn)
End Try
Return Dt
End Function
|
6- Método deletarRegistro() - exclui um aluno pelo código da tabela Alunos.
Public Sub deletarRegistro(ByVal codigo As Integer) Try
cn = getConexaoDB()
Dim myCmd As New OleDb.OleDbCommand
myCmd.Connection = cn
myCmd.CommandText = "DELETE FROM Alunos WHERE codigo = " & codigo myCmd.ExecuteNonQuery() Catch ex As Exception
Throw ex
Finally
closeConexaoDB(cn)
End Try
End Sub
|
7- Método atualizarDados() - Atualiza os dados de um aluno selecionado pelo código.
Public Sub atualizarDados(ByVal nome As String, strImagem As String, codigo As Integer, arrImagem() As Byte)
Try
cn = getConexaoDB()
Dim myCmd As New OleDb.OleDbCommand
myCmd.Connection = cn
myCmd.CommandText = "Update Alunos SET nome = '" & nome & "'," & "imagem = " & strImagem & " WHERE codigo =" & codigo
If strImagem = "?" Then
myCmd.Parameters.Add(strImagem, OleDb.OleDbType.Binary).Value = arrImagem
End If
myCmd.ExecuteNonQuery()
Catch ex As Exception
Throw ex
Finally
closeConexaoDB(cn)
End Try
End Sub
|
Note que em todos os métodos usamos o tratamento de erros Try/Catch/Finally onde o código do bloco Finally sempre será executado.
Alterando a camada de apresentação
Agora que temos uma camada de acesso aos dados criada e pronta para o uso vamos alterar o código do formulário form1.vb removendo toda a referência e código de acesso aos dados.
Vou mostrar a esquerda o código anterior usado e à esquerda no novo código que usa a nossa camada de acesso aos dados.
Remova as referências a System.Data e System.Data.OleDb do formulário.
Vamos criar uma instância da classe AcessoDados logo após a declaração do formulário:
Dim acc As New AcessoDadosNo evento Load do formulário que ocorre quando a aplicação for aberta vamos continuar a usar o código que chama a rotina CarregaDados();
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
CarregaDados()
End Sub
|
A rotina CarregaDados() vai acessar o banco de dados e selecionar todas as informações existentes e exibi-las no controle DataGridView no formulário form1;
Abaixo vemos à esquerda como era a rotina e à direita como ficou o novo código:
Note que estamos usando o objeto acc que é uma instância da classe AcessoDados e estamos chamando o método carregaDados()
Private Sub CarregaDados()
Dim cn As New OleDb.OleDbConnection
cn.ConnectionString = "Provider=Microsoft.Jet.OleDb.4.0; Data Source=c:\dados\Escola.mdb"
cn.Open()
Try
With Cmd
.CommandType = CommandType.Text
.CommandText = "SELECT * from Alunos"
.Connection = cn
End With
With Da
.SelectCommand = Cmd
Dt = New DataTable
.Fill(Dt)
dgvAlunos.DataSource = Dt
End With
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
|
Try dgvAlunos.DataSource = acc.carregaDados() Catch ex As Exception MsgBox(ex.Message) End Try
|
A seguir temos o código do evento Click do botão Incluir que acessa o banco de dados, abre uma conexão e inclui um novo registro na tabela Alunos usando uma instrução SQL INSERT INTO;
Á direita o código antigo e a esquerda o novo código onde chamamos o método incluirDados() da classe AcessoDados:
Private Sub btnIncluir_Click(sender As System.Object, e As System.EventArgs) Handles btnIncluir.Click
Dim cn As New OleDb.OleDbConnection
cn.ConnectionString = "Provider=Microsoft.Jet.OleDb.4.0; Data Source=c:\dados\Escola.mdb"
cn.Open()
Dim arrImagem() As Byte
Dim strImagem As String
Dim ms As New IO.MemoryStream
If txtNome.Text = String.Empty Then
MsgBox("Informe o nome do aluno")
txtNome.Focus()
Return
End If
'
If Not IsNothing(Me.picFoto.Image) Then
Me.picFoto.Image.Save(ms, Me.picFoto.Image.RawFormat)
arrImagem = ms.GetBuffer
strImagem = "?"
Else
arrImagem = Nothing
strImagem = "NULL"
End If
Dim myCmd As New OleDb.OleDbCommand
myCmd.Connection = cn
myCmd.CommandText = "INSERT INTO Alunos(nome, imagem) " & _
" VALUES( '" & Me.txtNome.Text & "'," & strImagem & ")"
If strImagem = "?" Then
myCmd.Parameters.Add(strImagem, OleDb.OleDbType.Binary).Value = arrImagem
End If
myCmd.ExecuteNonQuery()
MsgBox("Dados Salvos com sucesso!")
cn.Close()
CarregaDados()
End Sub
|
Private Sub btnIncluir_Click(sender As System.Object, e As System.EventArgs)
Handles btnIncluir.Click
Dim arrImage() As Byte
Dim strImage As String
Dim myMs As New IO.MemoryStream
If txtNome.Text = String.Empty Then
MsgBox("Informe o nome do aluno")
txtNome.Focus()
Return
End If
If Not IsNothing(Me.picFoto.Image) Then
Me.picFoto.Image.Save(myMs, Me.picFoto.Image.RawFormat)
arrImage = myMs.GetBuffer
strImage = "?"
Else
arrImage = Nothing
strImage = "NULL"
End If
Try
acc.incluirDados(txtNome.Text, arrImage, strImage)
MsgBox("Dados Salvos com sucesso!")
Catch ex As Exception
MsgBox("Erro ao incluir dados!")
End Try
CarregaDados()
End Sub
|
No evento Click do botão de comando Procurar o código abaixo chama a rotina Procurar();
Aqui não houve alteração.
Private Sub btnProcurar_Click(sender As System.Object, e As System.EventArgs) Handles btnProcurar.Click
If txtCodigo.Text = String.Empty Then
MsgBox("Informe o codigo do aluno")
Else
Procurar(Me.txtCodigo.Text)
End If
End Sub
|
A rotina Procurar() recebe o código do aluno, abre a conexão com o banco de dados e seleciona o aluno pelo seu código preenchendo um DataTable e populando os controles do formulário com os dados obtidos;
O novo código à direita chama o método procurarDados() e preenche um objeto aluno exibindo os dados no formulário:
Private Sub Procurar(ByVal codigo As Integer)
Dim cn As New OleDb.OleDbConnection
cn.ConnectionString = "Provider=Microsoft.Jet.OleDb.4.0; Data Source=c:\dados\Escola.mdb"
cn.Open()
Dim arrImagem() As Byte
Dim ms As New IO.MemoryStream
Dim da As New OleDb.OleDbDataAdapter("SELECT * FROM Alunos " & _
" WHERE codigo=" & codigo, cn)
Dim dt As New DataTable
da.Fill(dt)
If dt.Rows.Count > 0 Then
Me.txtCodigo.Text = dt.Rows(0).Item("codigo")
Me.txtNome.Text = dt.Rows(0).Item("nome") & ""
If Not IsDBNull(dt.Rows(0).Item("imagem")) Then
arrImagem = dt.Rows(0).Item("imagem")
For Each ar As Byte In arrImagem
ms.WriteByte(ar)
Next
'
Me.picFoto.Image = System.Drawing.Image.FromStream(ms)
Else
Me.picFoto.Image = _
System.Drawing.Image.FromFile(Application.StartupPath & "/semfoto.jpg")
End If
Me.btnIncluir.Enabled = False
Else
MsgBox("Registro não localizado")
End If
cn.Close()
End Sub
|
Private Sub Procurar(ByVal codigo As Integer)
Dim arrImage() As Byte = Nothing
Dim myMS As New IO.MemoryStream
Dim aluno1 As New Aluno
aluno1 = acc.procurarDados(codigo) If Not IsNothing(aluno1) Then Me.txtCodigo.Text = aluno1.Codigo
Me.txtNome.Text = aluno1.Nome
If Not IsDBNull(aluno1.Imagem) Then
Me.picFoto.Image = aluno1.Imagem
Else
Me.picFoto.Image = _
System.Drawing.Image.FromFile(Application.StartupPath & "/semfoto.jpg")
End If
Me.btnIncluir.Enabled = False
Else
MsgBox("Registro não localizado")
End If
End Sub
|
No evento Click do controle LinkLabel o código abre uma caixa de diálogo para que uma imagem seja selecionada e exibida no controle Image;
Aqui não houve alteração no código:
Private Sub lnkProcurar_LinkClicked(sender As System.Object, e As System.Windows.Forms.LinkLabelLinkClickedEventArgs) Handles lnkProcurar.LinkClicked
If Me.ofdImagem.ShowDialog = 1 Then
Me.picFoto.Image = System.Drawing.Image.FromFile(Me.ofdImagem.FileName)
Else
Me.picFoto.Image = System.Drawing.Image.FromFile(Application.StartupPath & "/semfoto.jpg")
End If
End Sub
|
No evento CellClick do controle DataGridView quando o usuário clicar em um célula do controle iremos selecionar o código da célula clicada e chamar a rotina Procurar passando este código;
Aqui não houve alteração no código:
Private Sub dgvAlunos_CellClick(sender As System.Object, e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgvAlunos.CellClick
Try
'Dim codigo As Integer = dgvAlunos.Rows(e.RowIndex).Cells(e.ColumnIndex).Value()
Dim codigo As Integer = dgvAlunos.Rows(e.RowIndex).Cells(0).Value()
Procurar(codigo)
Catch ex As Exception
MsgBox("Seleção Inválida. Clique em uma célula com dados.")
End Try
End Sub
|
No evento Click do botão Limpar limpamos os controles do formulário;
Aqui não houve alteração no código:
Private Sub btnLimpar_Click(sender As System.Object, e As System.EventArgs) Handles btnLimpar.Click
Me.txtCodigo.Text = ""
Me.txtNome.Text = ""
Me.picFoto.Image = Nothing
Me.txtCodigo.Focus()
Me.btnIncluir.Enabled = True
End Sub
|
O evento Click do botão Deletar será solicitada uma confirmação para excluir o registro selecionado; a seguir será aberta uma conexão com o banco de dados e o registro selecionado será deletado usando a instrução SQL DELETE FROM;
O novo código à direita chama o método deletarRegistro():
Private Sub btnDeletar_Click(sender As System.Object, e As System.EventArgs) Handles btnDeletar.Click
Dim resultado As DialogResult = MessageBox.Show("Confirma a exclusão deste registro ?", _
"Excluir", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
If resultado = vbYes Then
Dim cn As New OleDb.OleDbConnection
cn.ConnectionString = "Provider=Microsoft.Jet.OleDb.4.0; Data Source=c:\dados\Escola.mdb"
cn.Open()
If txtCodigo.Text = String.Empty Then
MsgBox("Informe o codigo do aluno")
txtNome.Focus()
Return
End If
Dim myCmd As New OleDb.OleDbCommand
myCmd.Connection = cn
myCmd.CommandText = "DELETE FROM Alunos WHERE codigo = " & txtCodigo.Text
myCmd.ExecuteNonQuery()
MsgBox("Dados excluídos com sucesso!")
cn.Close()
CarregaDados()
End If
End Sub
|
Private Sub btnDeletar_Click(sender As System.Object, e As System.EventArgs) Handles btnDeletar.Click Dim resultado As DialogResult = MessageBox.Show("Confirma a exclusão deste registro ?", _
"Excluir", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
If resultado = vbYes Then
Dim codigo As Integer
If txtCodigo.Text = String.Empty Then
MsgBox("Informe o codigo do aluno")
txtNome.Focus()
Return
Else
codigo = Convert.ToInt32(txtCodigo.Text)
End If
Try
acc.deletarRegistro(codigo)
MsgBox("Dados excluídos com sucesso!")
Catch ex As Exception
MsgBox(ex.Message)
End Try
CarregaDados()
End If
End Sub
|
No evento Click do botão Alterar abrimos uma conexão com o banco de dados e alteramos as informações do registro selecionado usando a instrução SQL UPDATE/SET;
Private Sub btnAlterar_Click(sender As System.Object, e As System.EventArgs) Handles btnAlterar.Click
Dim cn As New OleDb.OleDbConnection
cn.ConnectionString = "Provider=Microsoft.Jet.OleDb.4.0; Data Source=c:\dados\Escola.mdb"
cn.Open()
Dim arrImagem() As Byte
Dim strImagem As String
Dim ms As New IO.MemoryStream
If txtNome.Text = String.Empty Then
MsgBox("Informe o nome do aluno")
txtNome.Focus()
Return
End If
'
If Not IsNothing(Me.picFoto.Image) Then
Me.picFoto.Image.Save(ms, Me.picFoto.Image.RawFormat)
arrImagem = ms.GetBuffer
strImagem = "?"
Else
arrImagem = Nothing
strImagem = "NULL"
End If
Dim myCmd As New OleDb.OleDbCommand
myCmd.Connection = cn
myCmd.CommandText = "Update Alunos SET nome = '" & txtNome.Text & "'," & "imagem = " & strImagem & " WHERE codigo =" & txtCodigo.Text
If strImagem = "?" Then
myCmd.Parameters.Add(strImagem, OleDb.OleDbType.Binary).Value = arrImagem
End If
myCmd.ExecuteNonQuery()
MsgBox("Dados Alterados com sucesso!")
cn.Close()
CarregaDados()
End Sub
|
| Código anterior |
Abaixo o novo código que chama o método atualizarDados():
Private Sub btnAlterar_Click(sender As System.Object, e As System.EventArgs) Handles btnAlterar.Click
Dim arrImage() As Byte
Dim strImage As String
Dim myMs As New IO.MemoryStream
If txtNome.Text = String.Empty Then
MsgBox("Informe o nome do aluno")
txtNome.Focus()
Return
End If
If Not IsNothing(Me.picFoto.Image) Then
Me.picFoto.Image.Save(myMs, Me.picFoto.Image.RawFormat)
arrImage = myMs.GetBuffer
strImage = "?"
Else
arrImage = Nothing
strImage = "NULL"
End If
Try
acc.atualizarDados(txtNome.Text, strImage, txtCodigo.Text, arrImage)
MsgBox("Dados Alterados com sucesso!")
Catch ex As Exception
MsgBox(ex.Message)
End Try
CarregaDados()
End Sub
|
No evento Validating da caixa de texto txtNome usamos o controle ErrorProvider para validar o campo txtNome;
Aqui não houve alteração de código:
Private Sub txtNome_Validating(sender As System.Object, e As System.ComponentModel.CancelEventArgs) Handles txtNome.Validating
If (txtNome.Text.Trim().Length = 0) Then
erro.SetError(txtNome, "Informe o nome do aluno")
Else
erro.SetError(txtNome, "")
End If
End Sub
|
Executando a solução teremos a exibição do formulário conforme mostra a figura abaixo obtendo assim o mesmo resultado final:
![]() |
Dessa forma criamos uma camada de acesso a dados e aplicamos uma das principais regras das boas práticas : a separação de responsabilidades.
Podemos melhorar ainda mais nossa aplicação usando um ORM como o Entity Framework para remover todas as referências aos objetos ADO .NET e os comandos SQL e trabalhar somente com objetos.
Pegue o projeto completo
aqui:
CadastroAlunosAccess_CamadaAcessoDados.zip
Aguarde que em outro artigo eu vou mostrar como usar o Entity Framework e realizar o mapeamento ORM abstraindo assim os objetos ADO .NET e os comandos SQL.
Heb 2:17
Pelo que convinha que em tudo fosse feito semelhante a seus irmãos, para se tornar um sumo sacerdote misericordioso e fiel nas coisas concernentes a Deus, a fim de fazer propiciação pelos pecados do povo.Heb 2:18
Porque naquilo que ele mesmo, sendo tentado, padeceu, pode socorrer aos que são tentados.
Gostou ?
Compartilhe no Facebook
Compartilhe no Twitter
Referências: