VB .NET- Manutenção de dados com ListView, ADO .NET usando DAL - I
Este é um artigo para iniciantes e mostra como realizar a manutenção de dados usando a ADO .NET com a linguagem Visual Basic em um projeto Windows Forms onde o controle central será o controle ListView. |
O cenário será realizar a manutenção de usuários que estão armazenados em uma tabela Usuarios no banco de dados chamado Controle.mdb.
Vemos na figura abaixo a estrutura da tabela Usuarios e alguns dados que eu vou usar para testar o projeto.
Eu poderia realizar a tarefa de manutenção de dados usando diversas técnicas mas vou usar os recursos da ADO .NET e trabalhar com uma camada de acesso a dados e uma camada de negócios separando assim as funcionalidades da nossa aplicação. Mesmo em projetos pequenos esta é uma boa prática a qual você deve se habituar.
Embora o Domain Drive Design(DDD)tenha uma filosofia completamente diferente da que estamos seguindo (estamos começando com o banco de dados e não com o foco no negócio), nosso projeto vai procurar seguir as boas práticas usando os recursos da ADO .NET usando o Visual Basic 2010 Express Edition.
Antes de iniciar o projeto vamos dar uma olhada no formulário principal e explicar algumas funcionalidades do mesmo:
Abaixo temos o formulário principal do projeto onde é realizada a manutenção dos usuários da tabela Usuarios:
O Controle ListView esta sendo usado para exibir e manipular os dados de forma que ao clicar em uma linha do controle os dados são exibidos nas caixas de texto do formulário. Além disso vamos aplicar o efeito zebrado no controle e formatar as colunas.
Estamos usando também uma camada de acesso a dados simples com os recursos da ADO .NET (sem LINQ nem Entity Framework) e uma camada de negócios de forma a ter uma arquitetura em 3 camadas onde:
Vamos então criar um projeto do tipo Windows Forms Application no Visual Basic 2010 Express Edition no menu File -> New Project, com o nome SistemaControleAcesso;
Feito isso vamos criar uma pasta no projeto chamada Dados onde iremos colocar o banco de dados Controle.mdb. Clique com o botão direito do mouse sobre o nome do projeto e selecione Add-> New Folder e informe o nome Dados;
A seguir no menu Project selecione Add Class e inclua um template Class com o nome AcessoHelper.vb;
Neste arquivo iremos definir a nossa camada de acesso a dados. Ela será simples mas bem funcional.
Vamos criar uma camada de acesso a dados que no futuro poderá ser modificada para trabalhar com outros banco de dados como o SQL Server e um banco de dados ODBC embora no projeto estejamos usando o Microsoft Access por questão de simplicidade.
Abra o arquivo AcessoHelper.vb e defina no seu início os seguintes namespaces:
Imports System
Imports System.Data
Imports System.Data.Common
Imports System.Data.SqlClient
Imports System.Data.Odbc
Imports System.Data.OleDb
Imports System.IO
A seguir vamos definir a classe AcessoHelper implementando a interface IDisposable. Geralmente implementamos esta interface quando vamos tratar com tipos não gerenciados cono conexões de banco de dados e mesmo com código gerenciado como as classe .NET como System.IO.FileStream e assim termos mais segurança de que os objetos serão liberados após sua utilização pelo coletor de lixo.
Dessa forma vamos declarar a nossa classe da seguinte forma:
Public Class AcessoHelper
Implements IDisposable
Fazendo isso temos que implementar o seguinte método na classe:
Public
Sub Dispose1() Implements System.IDisposable.Dispose objConnection.Close() objConnection.Dispose() objCommand.Dispose() End Sub |
A seguir vamos declarar as variáveis objetos que iremos usar no projeto :
Private
strConnectionString As String
Private objConnection As DbConnection
Private objCommand As DbCommand
Private objFactory As DbProviderFactory = Nothing
Note que estamos usando a classe DbProviderFactory que representa um conjunto de métodos para criação de instâncias de implementação de provedores das classes de fonte de dados. Fizemos isso pois no futuro poderemos expandir a classe para ser usada com outros banco de dados sem ter que alterar muito o código.
O próximo passo é definir uma enumeração para tratar a conexão definindo se vamos fechá-la ou deixá-la aberta:
Public
Enum ConnectionState MantemConexaoAberta FechaConexaoAoSair End Enum |
Nota: Uma Enumeration oferece uma maneira fácil de trabalhar com conjunto de dados que estão relacionados a constantes. Assim , um Enumeration ou Enum é um nome simbólico para um conjunto de valores.
Após essas definições vamos criar o construtor da nossa classe conforme o código abaixo:
Public
Sub New() objFactory = OleDbFactory.Instance objConnection = objFactory.CreateConnection objCommand = objFactory.CreateCommand objConnection.ConnectionString = GetStringConnection() objCommand.Connection = objConnection End Sub |
Nota: O construtor é uma rotina que é invocada quando uma instância de uma classe é criada. No VB.NET esta rotina precisa ter o nome New para identificar o construtor.
O construtor inicia os objetos e define a string de conexão e a conexão com o banco de dados. O próximo passo é definir o método GetStringConnection() que obtém a string de conexão:
Public
Function GetStringConnection() As String Dim caminhoBD As String = GetCaminhoBD() & "\Dados\Controle.mdb" Dim strConexao As String = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & caminhoBD & ";Mode=ReadWrite;Persist Security Info=False" ' Retorna a string de conexão Return strConexao End Function |
Obs1: Este método retorna a string de conexão que foi definida via código o melhor seria colocar a string de conexão no arquivo App.Config e usar a classe ConfigurationManager para obter a string de conexão deste arquivo. Para isso teremos que incluir o namespace: System.Configuration e uma referência no projeto a System.Configuration e usar a seguinte linha de código: Dim strconexao = ConfigurationManager.ConnectionStrings("connectionstring").ConnectionString()
Obs2:
Podemos ainda usar o recurso My
para obter a string de conexão definida no arquivo App.Config
usando o seguinte código:
Dim strconexao as String =
My.Settings.ControleAcessoConnectionString
Vamos definir o método GetCaminhoBD() que vai definir o caminho do banco de dados que estamos usando. Lembre que o banco de dados esta na pasta Dados do projeto.
Public
Shared Function GetCaminhoBD() As String Dim caminhoArquivo As String = Application.StartupPath If caminhoArquivo.IndexOf("\bin\Debug") <> -1 Then caminhoArquivo = caminhoArquivo.Replace("\bin\Debug", "") ElseIf caminhoArquivo.IndexOf("\bin\Release") <> -1 Then caminhoArquivo = caminhoArquivo.Replace("\bin\Release", "") End If Return caminhoArquivo End Function |
Neste código retornamos o caminho da aplicação de forma que o caminho do banco de dados será definido a partir da pasta \Dados que criamos no projeto.
A próxima etapa será definir os métodos para acessar e persistir informações no banco de dados. Para tornar as coisas mais simples eu só vou definir os métodos que o projeto irá usar e o nosso projeto irá realizar as seguintes operações:
A seguir temos os métodos ExecuteNonQuery definidos na classe AcessoHelper da camada de acesso a dados:
Public Function ExecuteNonQuery(ByVal query As String) As Integer Return ExecuteNonQuery(query, CommandType.Text, ConnectionState.FechaConexaoAoSair) End Function Public Function ExecuteNonQuery(ByVal query As String, ByVal commandtype As CommandType) As Integer Return ExecuteNonQuery(query, commandtype, ConnectionState.FechaConexaoAoSair) End Function Public Function ExecuteNonQuery(ByVal query As String, ByVal connectionstate As ConnectionState) As Integer Return ExecuteNonQuery(query, CommandType.Text, connectionstate) End Function Public Function ExecuteNonQuery(ByVal query As String, ByVal commandtype As CommandType, ByVal connectionstate As ConnectionState) As Integer objCommand.CommandText = query objCommand.CommandType = commandtype Dim i As Integer = -1 Try If objConnection.State = System.Data.ConnectionState.Closed Then objConnection.Open() End If i = objCommand.ExecuteNonQuery Catch ex As Exception Throw (ex) Finally objCommand.Parameters.Clear() If connectionstate = connectionstate.FechaConexaoAoSair Then objConnection.Close() End If End Try Return i End Function |
Porque definimos 4 métodos ExecuteNonQuery ?
Definimos 4 métodos sobrecarregados para ter mais flexibilidade de forma a podemos passar para o métodos parâmetros diferentes conforme a nossa necessidade. Assim temos:
Nosso projeto iremos usar somente a primeira opção mas eu resolvi deixar os demais métodos para você perceber uma característica de uma linguagem orientada a objetos : a sobrecarga de métodos.
A seguir temos a definição dos métodos ExecuteReader da camada de acesso a dados:
Public Function ExecuteReader(ByVal query As String) As DbDataReader Return ExecuteReader(query, CommandType.Text, ConnectionState.FechaConexaoAoSair) End Function Public Function ExecuteReader(ByVal query As String, ByVal commandtype As CommandType) As DbDataReader Return ExecuteReader(query, commandtype, ConnectionState.FechaConexaoAoSair) End Function Public Function ExecuteReader(ByVal query As String, ByVal connectionstate As ConnectionState) As DbDataReader Return ExecuteReader(query, CommandType.Text, connectionstate) End Function Public Function ExecuteReader(ByVal query As String, ByVal commandtype As CommandType, ByVal connectionstate As ConnectionState) As DbDataReader objCommand.CommandText = query objCommand.CommandType = commandtype Dim reader As DbDataReader = Nothing Try If objConnection.State = System.Data.ConnectionState.Closed Then objConnection.Open() End If If connectionstate = connectionstate.FechaConexaoAoSair Then reader = objCommand.ExecuteReader(CommandBehavior.CloseConnection) Else reader = objCommand.ExecuteReader End If Catch ex As Exception Throw (ex) Finally objCommand.Parameters.Clear() End Try Return reader End Function |
Aqui também definimos 4 métodos sobrecarregados mas na verdade o projeto irá usar somente o primeiro onde passamos somente a string de consulta para o método.
Além destes poderíamos definir também os métodos :
Obs: No projeto estes métodos estão comentados. Para usá-los basta descomentar.
Como estamos vamos usar parâmetros nas instruções SQL e consultas precisamos definir um método para podermos passar os parâmetros que serão usados nas instruções SQL. Para isso vamos criar o método AddParameter() conforme mostrado a seguir:
Public Function AddParameter(ByVal name As String, ByVal value As Object) As Integer Dim p As DbParameter = objFactory.CreateParameter p.ParameterName = name p.Value = value Return objCommand.Parameters.Add(p) End Function Public Function AddParameter(ByVal parameter As DbParameter) As Integer Return objCommand.Parameters.Add(parameter) End Function |
Para encerrar vamos definir um método para gerar um Hash da senha de forma que vamos armazenar não o texto da senha mas o seu HASH aumentando assim a segurança da informação. Segue abaixo o código do método GerarHash que obtém um texto e retorna um hash do mesmo :
Public Function GerarHash(ByVal Valor As String) As String Dim Sha As New System.Security.Cryptography.SHA1Managed Sha.ComputeHash(System.Text.Encoding.Default.GetBytes(Valor)) Return Convert.ToBase64String(Sha.Hash) End Function |
Nota: Um hash é uma seqüencia de letras ou números geradas por um algorítmo de Hash. Na criptografia, o hash serve para garantir a integridade da mensagem, onde o gerador (ou emissor) da mensagem, submete-a a um algoritmo hash, o qual produzirá um valor hash.
Com esses métodos já temos a camada de acesso a dados pronta para nos dar o suporte necessário para consultar e persistir informações.
A próxima etapa é definir uma camada de negócios para receber as instruções da camada de interface e por último definir a camada de interface e criar as requisições necessárias as demais camadas para acessar e persistir informações dos usuários.
Aguarde a continuação do artigo em : VB .NET- Manutenção de dados com ListView, ADO .NET usando DAL - II
Eu sei é apenas VB .NET, mas eu gosto...
Referências: