C# - ListView - CRUD básico com SQL Server em 3 camadas - II


 Neste artigo vamos recordar como realizar o CRUD básico usando o banco de dados SQL Server em uma aplicação Windows Forms aplicando uma arquitetura em camadas.

Continuando a primeira parte do artigo vamos prosseguir 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 vamos abrir o projeto BLL e incluir uma nova classe chamada UsuarioBLL 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:

Dessa forma vamos declarar a nossa classe da seguinte forma:

using System;
using System.Data.Common;
namespace BLL
{
    public class UsuarioBLL
    {
        public AcessoHelper db = new AcessoHelper();
        public void cadastraUsuario(string nome, string email, string senha)
        {
            try
            {
                string sql = "Insert Into Usuarios(nome,email,senha) values (@nome,@email,@senha)";
                db.AddParameter("@nome", nome);
                db.AddParameter("@email", email);
                db.AddParameter("@senha", senha);
                db.ExecuteNonQuery(sql);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public void alterarUsuario(string nome, string email, string senha, int usuarioid)
        {
            try
            {
                string sql = "Update Usuarios set nome=@nome, email=@email, senha=@senha where 
usuarioid=@usuarioid";
                db.AddParameter("@nome", nome);
                db.AddParameter("@email", email);
                db.AddParameter("@senha", senha);
                db.AddParameter("@usuarioid", usuarioid);
                db.ExecuteNonQuery(sql);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public void excluirUsuario(int usuarioid)
        {
            try
            {
                string sql = "Delete From usuarios where usuarioid=@usuarioid";
                db.AddParameter("@usuarioid", usuarioid);
                db.ExecuteNonQuery(sql);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public DbDataReader Procurar(int usuarioid)
        {
            try
            {
                string sql = "SELECT * FROM usuarios WHERE usuarioid=@usuarioid";
                db.AddParameter("@usuarioid", usuarioid);
                return db.ExecuteReader(sql);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public bool ProcurarPorNome(string nome)
        {
            DbDataReader dr = null;
            try
            {
                string sql = "SELECT * FROM usuarios WHERE nome=@nome";
                db.AddParameter("@nome", nome);
                dr = db.ExecuteReader(sql);
                if (dr.HasRows)
                    return true;
                else
                    return false;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                dr.Close();
            }
        }
        public DbDataReader Selecionar()
        {
            try
            {
                string sql = "SELECT * FROM usuarios";
                return db.ExecuteReader(sql);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        public string gerarHashSenha(object texto)
        {
            return db.GerarHash(texto.ToString());
        }
    }
}

Esta classe utiliza os métodos definidos na classe AcessoHelper para realizar as operações CRUD no banco de dados usando os métodos ExecuteNonQuery e ExecuteReader.

Observe que no código estamos usando instruções SQL inline, mas você pode melhorar esse código substituindo as instruções por procedimentos armazenados(stored procedures). Essa abordagem é mais robusta e evita a injeção SQL.

Outro detalhe importante é que não estamos usando uma classe DTO para transferir os dados dos usuários para a camada DAL. Seria mais recomendado criar uma classe Usuario e ao invès de passar os dados como valores primitivos passar um objeto Usuario. Vou deixar isso por sua conta...

Criando a interface com o usuário - UI

A nossa interface é o formulário Form1.cs que é composto pelos controles ListView, Button, Label e TextBox e cujo leiaute é mostrado na figura abaixo:

Os namespaces usados neste formulário são:

using BLL;
using System;
using System.Data.Common;
using System.Drawing;
using System.Windows.Forms;


No início do formulário definimos algumas variáveis que iremos usar e criamos uma instância da classe UsuarioBLL pois vou usar alguns métodos desta classe:

UsuarioBLL acc = new UsuarioBLL();
int codigo = 0;
string senhaAtual = "";
string nomeAtual = "";

Aqui poderiamos usar a injeção de dependência com algum componente como o Ninject, Unity, etc. para livrar a dependência da classe UsuarioBLL.

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 void Form1_Load(object sender, EventArgs e)
        {
            try
            {
                lvUsuarios.View = View.Details;
                lvUsuarios.FullRowSelect = true;
                lvUsuarios.GridLines = true;
                PreencheListView(ref lvUsuarios);
                AlternarCoresdeFundo(lvUsuarios, Color.Aqua, Color.LightGreen);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

O método PreencherListView() tem o código exibido abaixo:

        public void PreencheListView(ref ListView cListView)
        {
            ColumnHeader lvwColumn;
            ListViewItem itmListItem;
            // isso não deveria estar presente na camada de interface
            // por pura preguiça em criar uma rotina deixei este código aqui
            DbDataReader dados = acc.Selecionar();
            short shtCntr;
            int incremento = 0;
            cListView.Clear();
            for (shtCntr = 0; shtCntr <= dados.FieldCount - 1; shtCntr++)
            {
                lvwColumn = new ColumnHeader();
                lvwColumn.Text = dados.GetName(shtCntr);
                cListView.Columns.Add(lvwColumn.Text, 65 + incremento, HorizontalAlignment.Left);
                incremento = incremento + 40;
            }
            while (dados.Read())
            {
                itmListItem = new ListViewItem();
                itmListItem.Text = dados[0].ToString();
                for (shtCntr = 1; shtCntr <= dados.FieldCount - 1; shtCntr++)
                {
                    if (dados.IsDBNull(shtCntr))
                        itmListItem.SubItems.Add("");
                    else
                        itmListItem.SubItems.Add(dados.GetString(shtCntr));
                }
                cListView.Items.Add(itmListItem);
            }
            dados.Close();
        }

O código do método AlternarCoresdeFundo() é mostrado a seguir:

        public void AlternarCoresdeFundo(ListView lst, Color color1, Color color2)
        {
            // percorre cada ListViewItem no ListView
            foreach (ListViewItem item in lst.Items)
            {
                if ((item.Index % 2) == 0)
                    item.BackColor = color1;
                else
                    item.BackColor = color2;
            }
        }

Quando o usuário seleciona um item no controle ListView os controles TextBox devem ser preenchidos com os respectivos valores e para isso usamos o evento SelectedIndexChanged do controle ListView obtendo o código do item selecionado, o nome e senha atuais e chamando a rotina PreencheControles() que vemos a seguir:

        private void lvUsuarios_SelectedIndexChanged(object sender, EventArgs e)
        {
            try
            {
                if (lvUsuarios.SelectedItems.Count > 0)
                {
                    //pega o Id do item selecionado
                    codigo = Convert.ToInt32(lvUsuarios.Items[lvUsuarios.SelectedIndices[0]].Text);
                    //pega o nome e a senha do item selecionado
                    nomeAtual = lvUsuarios.SelectedItems[0].SubItems[1].Text;
                    senhaAtual = lvUsuarios.SelectedItems[0].SubItems[2].Text;
                    PreencheControles(acc.Procurar(codigo));
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

Para preencher os controles TextBox com os dados usamos o método PreencheControles() :

       private void PreencheControles(DbDataReader dados)
        {
            try
            {
                while (dados.Read())
                {
                    txtID.Text = dados["usuarioid"].ToString();
                    txtNome.Text = dados["nome"].ToString();
                    txtSenha.Text = dados["senha"].ToString();
                    txtEmail.Text = dados["email"].ToString();
                    senhaAtual = dados["senha"].ToString();
                }
                dados.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            }
        }

Falta agora apenas definir um método para validar os dados que o usuário vai informar no formulário.

A validação pode ser feita usando diversos critérios, no exemplo estou validando apenas quando os valores informados não forem vazios e a senha tiver mais que 6 caracteres.

Abaixo o método ValidaDados() possui o seguinte código:

        private bool ValidaDados()
        {
            if (txtNome.Text == string.Empty | txtSenha.Text == string.Empty | txtEmail.Text == string.Empty)
            {
                MessageBox.Show("Dados incompletos/inválidos...");
                txtNome.Focus();
                return false;
            }
            else if (txtSenha.TextLength < 6)
            {
                MessageBox.Show("A senha deve ter no mínimo 6 caracteres...");
                txtSenha.Focus();
                return false;
            }
            else
                return true;
        }

Agora falta implementar as funcionalidades para Incluir, Atualizar e Excluir usuários no formulário. Faremos isso em cada evento Click dos botões de comando.

Aguarde a próxima parte do artigo.

"Sujeitai-vos, pois, a Deus, resisti ao diabo, e ele fugirá de vós." Tiago 4:7

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 ?

Quer aprender a criar aplicações Web Dinâmicas usando a ASP .NET MVC 5 ?

Referências:


José Carlos Macoratti