VB .NET- Manutenção de dados com ListView, ADO .NET usando DAL - II
Na primeira parte deste artigo (escrita a alguns meses atrás) - VB .NET- Manutenção de dados com ListView, ADO .NET usando DAL - eu apresentei a proposta de criar 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 era o controle ListView. |
A proposta incluía adotar as boas práticas criando a aplicação em camadas e na primeira parte eu já havia criado a classe AcessoHelper que continha os métodos da camada de acesso a dados prontos para nos dar o suporte necessário para consultar e persistir informações.
A próxima etapa seria 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 às demais camadas para acessar e persistir informações dos usuários.
Como me envolvi em outros projetos mais importantes acabei esquecendo de continuar o projeto e como recebi muitos emails para continuar o projeto eu decidi fazê-lo sob algumas condições.
Primeiro gostaria de dizer que o projeto é bem básico e voltado para quem já tem um conhecimento sobre ADO .NET e deseja melhorar a arquitetura de seus projetos adotando as boas práticas. Eu dou uma introdução nesse assunto criando a camada de acesso a dados de uma forma bem simples, sem usar interfaces nem classes abstratas mas apenas um classe concreta que implementa a interface IDisposable. Isso é o básico, mas já é um avanço se comparado com a metodologia de colocar o código de acesso a dados no formulário da aplicação.
Bem, como dizia eu vou continuar o artigo mas para não tomar muito tempo eu vou simplificá-lo e não vou criar a camada de negócios simplesmente por que não estou com tempo e por que nesta camada colocamos as regras de negócio e validações de negócio e nossa aplicação é um simples cadastro de usuários onde estamos realizando as operações CRUD. Mesmo sem usar a camada de negócios seria bom criá-la deixando-a pronta para uma eventual mudança dos requisitos e surgimento de novas regras de negócio. Eu não vou fazer isso vou instanciar a camada de acesso a dados diretamente na camada de interface (violando assim as boas práticas).
Na verdade o projeto era mais ambicioso , eu pretendia criar um controle de acessos básico onde poderíamos atribuir os acessos aos formulários da aplicação aos usuários. O projeto completo já contém os formulário prontos para implementar esta funcionalidade.
Feitas as explicações vamos continuar com a manutenção de usuários implementando as funcionalidades CRUD (Create, Update, Delete)...
Implementando as operações CRUD
Para implementar as funcionalidades de inclusão, alteração e exclusão eu vou criar uma nova classe chamada UsuarioDAL e nesta classe definir os métodos específicos para incluir, excluir, alterar e procurar usuários. Essa classe ira conter os seguintes métodos:
No menu Project selecione Add Class e inclua um template Class com o nome UsuarioDAL.vb;
O código desta classe é dado a seguir:
Imports System.Data Imports System.Data.OleDb Public Class UsuarioDAL Public db As New AcessoHelper() Public Sub cadastraUsuario(ByVal nome As String, ByVal cargo As String, ByVal senha As String) Try Dim sql As String = "Insert Into Usuarios(nome,cargo,senha) values (@nome,@cargo,@senha)" db.AddParameter("@nome", nome) db.AddParameter("@cargo", cargo) db.AddParameter("@senha", senha) db.ExecuteNonQuery(sql) Catch ex As Exception Throw ex End Try End Sub Public Sub alterarUsuario(ByVal nome As String, ByVal cargo As String, ByVal senha As String, ByVal usuarioid As Integer) Try Dim sql As String = "Update Usuarios set nome=@nome, cargo=@caro, senha=@senha where usuarioid =@usuarioid" db.AddParameter("@nome", nome) db.AddParameter("@cargo", cargo) db.AddParameter("@senha", senha) db.AddParameter("@usuarioid", usuarioid) db.ExecuteNonQuery(sql) 'MessageBox.Show("Usuário alterado com sucesso.", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Warning) Catch ex As Exception Throw ex End Try End Sub Public Sub excluirUsuario(ByVal usuarioid As Integer) Try Dim sql As String = "Delete From usuarios where usuarioid =@usuarioid" db.AddParameter("@usuarioid", usuarioid) db.ExecuteNonQuery(sql) 'MessageBox.Show("Usuário alterado com sucesso.", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Warning) Catch ex As Exception Throw ex End Try End Sub Public Function Procurar(ByVal usuarioid As Integer) As OleDbDataReader Try Dim sql As String = "SELECT * FROM usuarios WHERE usuarioid=@usuarioid" db.AddParameter("@usuarioid", usuarioid) Return db.ExecuteReader(sql) Catch ex As Exception Throw ex End Try End Function Public Function ProcurarPorNome(ByVal nome As String) As Boolean Dim dr As OleDbDataReader = Nothing Try Dim sql As String = "SELECT * FROM usuarios WHERE nome=@nome" db.AddParameter("@nome", nome) dr = db.ExecuteReader(sql) If dr.HasRows Then Return True Else Return False End If Catch ex As Exception Throw ex Finally dr.Close() End Try End Function Public Function Selecionar() As OleDbDataReader Try Dim sql As String = "SELECT * FROM usuarios" Return db.ExecuteReader(sql) Catch ex As Exception Throw ex End Try End Function Public Sub PreencheListView(ByRef cListView As ListView, ByRef dados As OleDbDataReader) Dim lvwColumn As ColumnHeader Dim itmListItem As ListViewItem Dim shtCntr As Short cListView.Clear() For shtCntr = 0 To dados.FieldCount() - 1 lvwColumn = New ColumnHeader() lvwColumn.Text = dados.GetName(shtCntr) cListView.Columns.Add(lvwColumn) Next Do While dados.Read itmListItem = New ListViewItem() itmListItem.Text = dados(0) For shtCntr = 1 To dados.FieldCount() - 1 If dados.IsDBNull(shtCntr) Then itmListItem.SubItems.Add("") Else itmListItem.SubItems.Add(dados.GetString(shtCntr)) End If Next shtCntr cListView.Items.Add(itmListItem) Loop End Sub Public Function gerarHashSenha(ByVal texto) As String Return db.GerarHash(texto) End Function End Class |
Esta classe utiliza os métodos definidos na classe AcessoHelper para realizar as operações CRUD no banco de dados.
Na figura abaixo temos uma visão das camadas usadas em nosso projeto:
Agora já podemos definir implementar na interface as chamadas aos métodos definidos nas classes UsuarioDAL e AcessoHelper.
Definindo o código da interface do Usuário
A nossa interface é o formulário frmUsuarios.vb que é composto pelos controles ListView, Button, Label e TextBox e cujo leiaute é mostrado na figura abaixo:
O formulário possui além dos botões de comando que implementa as funcionalidades que desejamos, algumas rotinas usadas na seleção e carga de dados.
No evento Load do formulário temos o código que define algumas características do ListView : a visão detalhes, a exibição das linhas de grade e o destaque da linha na seleção de um item.
A seguir é feita a chamada para as rotinas PreencheListView() e AlternarCoresdeFundo que preenche o ListView e alterna as cores de exibição no controle.
Private Sub frmUsuarios_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Try With lvUsuarios .View = View.Details .FullRowSelect = True .GridLines = True End With PreencheListView(lvUsuarios) AlternarCoresdeFundo(lvUsuarios, Color.Aqua, Color.LightGreen) Catch ex As Exception MessageBox.Show(ex.Message) End Try End Sub |
A rotina PreencheListView possui o seguinte código:
Public Sub PreencheListView(ByRef cListView As ListView) Dim lvwColumn As ColumnHeader Dim itmListItem As ListViewItem 'isso não deveria estar presente na camada de interface 'por pura preguiça em criar uma rotina deixei este código aqui Dim dados As OleDbDataReader = acc.Selecionar() Dim shtCntr As Short Dim incremento As Integer = 0 cListView.Clear() For shtCntr = 0 To dados.FieldCount() - 1 lvwColumn = New ColumnHeader() lvwColumn.Text = dados.GetName(shtCntr) cListView.Columns.Add(lvwColumn.Text, 60 + incremento, HorizontalAlignment.Left) incremento = incremento + 30 Next Do While dados.Read itmListItem = New ListViewItem() itmListItem.Text = dados(0) For shtCntr = 1 To dados.FieldCount() - 1 If dados.IsDBNull(shtCntr) Then itmListItem.SubItems.Add("") Else itmListItem.SubItems.Add(dados.GetString(shtCntr)) End If Next shtCntr cListView.Items.Add(itmListItem) Loop dados.Close() End Sub |
O código da rotina AlterarCoresdeFundo é mostrada a seguir:
Public Sub AlternarCoresdeFundo(ByVal lst As ListView, ByVal color1 As Color, ByVal color2 As Color) 'percorre cada ListViewItem no ListView For Each item As ListViewItem In lst.Items If (item.Index Mod 2) = 0 Then item.BackColor = color1 Else item.BackColor = color2 End If Next End Sub |
Quando é feita uma seleção no controle ListView os controles TextBox devem ser preenchidos com os respectivos valores e para isso usamos o evento SelectedIndexChanged do controle obtendo o código do item selecionado e chamando a rotina PreencheControles();
Private Sub lvUsuarios_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles lvUsuarios.SelectedIndexChanged Try If lvUsuarios.SelectedItems.Count > 0 Then 'Dim i As Integer = Convert.ToInt32(lvUsuarios.SelectedItems(0).SubItems(0).Text) 'Dim j As Integer = Convert.ToInt32(lvUsuarios.Items(i).Text) 'codigo = Convert.ToInt32(lvUsuarios.FocusedItem.SubItems(0).Text) codigo = Convert.ToInt32(lvUsuarios.Items(lvUsuarios.SelectedIndices(0)).Text) PreencheControles(acc.Procurar(codigo)) End If Catch ex As Exception MessageBox.Show(ex.Message) End Try End Sub |
O código da rotina PreencheControles que preenche cada caixa de texto com o valor o item selecionado é o seguinte:
Private Sub PreencheControles(ByVal dados As OleDbDataReader) Try Do While dados.Read txtUsuario.Text = dados("usuarioid") txtNome.Text = dados("nome") txtCargo.Text = dados("cargo") txtSenha.Text = dados("senha") senhaAtual = dados("senha") Loop dados.Close() Catch ex As Exception MessageBox.Show(ex.Message, "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Warning) End Try End Sub |
Além disso temos a rotina ValidaDados que verifica se as caixas de texto estão vazias e cujo código vemos a seguir:
Private Function ValidaDados() As Boolean If txtNome.Text = String.Empty Or txtSenha.Text = String.Empty Or txtCargo.Text = String.Empty Then MessageBox.Show("Dados incompletos/inválidos...") Return False Else Return True End If End Function |
Vejamos agora a implementação das funcionalidades Incluir, Atualizar e Excluir usuários no formulário.
Antes de iniciar devemos declarar as seguintes variáveis no início do formulário:
Dim acc As New
UsuarioDAL
Dim codigo As Integer = 0
Dim senhaAtual As String = ""
Dim nomeAtual As String = ""
1 - Incluindo um usuário
O código existente no evento Click do botão Incluir é dado abaixo:
Private Sub btnIncluir_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnIncluir.Click Try If ValidaDados() Then If acc.ProcurarPorNome(txtNome.Text) Then MessageBox.Show("Já existe usuário cadastrado com este login. Tente outro nome para o login.", "Login já Cadastrado", MessageBoxButtons.OK, MessageBoxIcon.Information) txtNome.Focus() Return End If acc.cadastraUsuario(txtNome.Text, txtCargo.Text, acc.gerarHashSenha(txtSenha.Text)) MessageBox.Show("Usuário incluido com sucesso.", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Warning) PreencheListView(lvUsuarios) AlternarCoresdeFundo(lvUsuarios, Color.Aqua, Color.LightGreen) End If Catch ex As Exception MessageBox.Show(ex.Message) End Try End Sub |
O código após validar os dados informados pelo usuário verifica se o não existe um nome de login já cadastrado para o nome informado usando a rotina ProcurarPorNome da classe UsuarioDAL.
Para incluir o usuário foi chamada o método cadastraUsuario da classe UsuarioDAL.
2 - Alterando um usuário
O código existente no evento Click do botão Atualizar é mostrado a seguir:
Private Sub btnAtualizar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnAtualizar.Click Try If ValidaDados() Then If Not nomeAtual.Equals(txtNome.Text) Then If acc.ProcurarPorNome(txtNome.Text) Then MessageBox.Show("Já existe usuário cadastrado com este login. Tente outro nome para o login.", "Login já Cadastrado", MessageBoxButtons.OK, MessageBoxIcon.Information) txtNome.Focus() Return End If End If If senhaAtual.Equals(txtSenha.Text) Then acc.alterarUsuario(txtNome.Text, txtCargo.Text, txtSenha.Text, txtUsuario.Text) Else acc.alterarUsuario(txtNome.Text, txtCargo.Text, acc.gerarHashSenha(txtSenha.Text), txtUsuario.Text) End If MessageBox.Show("Usuário atualizado com sucesso.", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Warning) PreencheListView(lvUsuarios) AlternarCoresdeFundo(lvUsuarios, Color.Aqua, Color.LightGreen) End If Catch ex As Exception MessageBox.Show(ex.Message) End Try End Sub |
Para alterar um usuário primeiro validamos os dados informados para não permitir valores inválidos.
Em seguida verificamos se o nome esta sendo alterado (Not nomeAtual.Equals(txtNome.Text) e neste caso verificamos ainda se o nome já não esta cadastrado.
Devemos também verificar se a senha não esta sendo alterada (senhaAtual.Equals(txtSenha.Text) e se estiver devemos gerar o Hash para a nova senha informada.
Para alterar o usuário foi chamada o método alterarUsuario da classe UsuarioDAL.
3 - Excluindo um usuário
O código existente no evento Click do botão Excluir é exibido a seguir:
Private Sub btnExcluir_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExcluir.Click Dim resultado As DialogResult = MessageBox.Show("Confirma exclusão deste usuário ?", "Confirma Exclusão", MessageBoxButtons.YesNo, MessageBoxIcon.Question) If resultado = DialogResult.Yes Then Try acc.excluirUsuario(txtUsuario.Text) MessageBox.Show("Usuário excluido com sucesso.", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Warning) PreencheListView(lvUsuarios) AlternarCoresdeFundo(lvUsuarios, Color.Aqua, Color.LightGreen) Catch ex As Exception MessageBox.Show("Erro ao excluir o usuário.", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Warning) End Try End If End Sub |
Para excluir um usuário foi chamada o método excluirUsuario da classe UsuarioDAL.
Executando o projeto iremos obter:
Com isso conclui o artigo e mostrei, embora com algumas simplificações (que você pode ajustar melhorando o código) como realizar as operações de manutenção de dados usando um controle ListView com ADO .NET em camadas.
Pegue o projeto completo aqui: SistemaControleAcesso.zip
Eu sei é apenas VB .NET, mas eu gosto...
Referências: