C# - CRUD Básico com DataGridView


Eu já escrevi dezenas de artigos sobre o DataGridView, a maioria usando a linguagem VB .NET, e hoje eu retorno ao tema desta vez abordando o assunto com a linguagem C#. 

Este artigo é para quem esta iniciando com a linguagem C# e precisa aprender a realizar as tarefas básicas com o DataGridView como preencher o controle, obter os valores de uma linha selecionada e incluir e excluir dados.

A teoria sobre o DataGridView, seus eventos e propriedades pode ser consultada nas referências do artigo.

Neste artigo vou preencher o DataGridView com dados de uma tabela do SQL Server LocalDb usando o Visual Studio 2012 Express for desktop. (Para facilitar o entendimento vou trabalhar apenas com uma tabela.)

Vou criar uma camada de acesso a dados chamada DAL onde a classe SQLHelper será responsável pelo acesso e persistência dos dados. Assim estamos separando as responsabilidades e poderemos reutilizar o código em outros projetos.

Eu não estou usando uma camada de negócios por pura preguiça e também para não alongar muito o artigo mas essa camada é muito importante e deve sempre ser criada em aplicações de produção.

Por não criar a camada de negócios eu estou tendo que referenciar na camada de apresentação o namespace System.Data.SqlClient para definir os parâmetros a serem informados para a camada de acesso a dados e isso deveria ser feito pela camada de negócios.

Para não ficar muito extensa eu vou definir na classe SQLHelper apenas os métodos que iremos usar no projeto mas você pode estender a classe ajustando-a às suas necessidades.

Definindo o banco de dados e a tabela

Vou criar um banco de dados no SQL Server usando o próprio ambiente do Visual Studio. Podemos fazer isso antes ou depois de criar a solução.

Abra o Visual Studio 2012 Express for desktop e visualize a janela DataBase Explorer;

Clique com o botão direito sobre Data Connections e clique em Add Connection;

1- SQL Server Express LocalDB

SQL Server Express LocalDB é uma versão leve do SQL Server que tem muitas características de programação de um banco de dados SQL Server. O SQL Server Express LocalDB é executado no modo de usuário e tem uma instalação rápida sem a necessidade de configuração.

No Microsoft SQL Server, o banco de dados ou qualquer código Transact-SQL podem ser movidos de SQL Server Express LocalDB para o SQL Server e SQL Azure, sem quaisquer passos de atualização.

Então, o SQL Server Express LocalDB pode ser usado como um ambiente de desenvolvimento para aplicações que utilizem todas as edições do SQL Server.

O SQL Server Express LocalDB permite recursos como procedimentos armazenados, funções definidas pelo usuário e agregados, Integração com NET Framework, tipos espaciais e outros recurso que não estão disponíveis no SQL Server Compact.

Ao clicar no botão OK será apresentada uma mensagem de que o arquivo não existe. Confirme para criar o arquivo.

Para criar a tabela, na janela DataBase Explorer clique com o botão direito sobre o objeto Tables e clique em Add New Table. A seguir defina a seguinte estrutura para esta tabela:

Salve a tabela com o nome Alunos clicando no botão Update (parte superior esquerda).

Podemos incluir alguns dados na tabela clicando com o botão direito do mouse sobre ela e a seguir em Show Table Data e digitando diretamente os dados nas colunas da tabela.

Abaixo temos a tabela com alguns dados:

Para concluir essa etapa vamos armazenar a string de conexão no arquivo App.Config para depois obtê-la via código.

Como a string de conexão esta sendo obtida a partir do arquivo de configuração App.Config vamos abrir este arquivo e incluir a informação da string de conexão do banco de dados Cadastro.mdf:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
  <connectionStrings>
    <add name="CadastroConexaoSQLServer" connectionString=
"Data Source=.\sqlexpress;Initial Catalog=Cadastro;Integrated Security=True"  providerName="System.Data.SqlClient" />
  </connectionStrings>
</configuration>

Criando a solução Windows Forms

Abra o Visual Studio 2012 Express for desktop e clique em New Project;

Selecione a linguagem Visual Basic e o template Windows Forms Application informando o nome DataGridView_Basico;

Inclua os seguintes controles a partir da Toolbox no formulário form1.vb;

Disponha os controles no formulário conforme o leiaute abaixo:

Agora vamos criar a camada de acesso a dado para depois voltarmos ao nosso projeto Windows Forms que é a nossa camada de apresentação.

Criando a camada de Acesso a Dados

A camada de acesso a dados será representada por um projeto do tipo Class LIbrary com o nome DAL onde teremos a classe SQLHelper onde teremos os métodos para acessar e persistir informações no banco de dados.

No menu FILE clique em Add -> New Project;

Selecione o template Class Library e informe o nome DAL;

Para que possamos acessar a informação da string de conexão no arquivo App.Config temos que incluir uma referência no projeto a System.Configuration. No menu PROJECT clique em Add Reference e selecione o item System.Configuration conforme figura abaixo e clique em OK;

A seguir renomeie a classe Class1.cs criada para SQLHelper e inclua o código a seguir neste arquivo:

using System.Data.SqlClient;
using System.Data;
using System.Configuration;

namespace DAL
{
    public class SQLHelper
    {
        public static string conection = ConfigurationManager
                                   .ConnectionStrings["CadastroConexaoSQLServer"].ConnectionString;

        public static DataTable ExecuteDataTable(string connectionString, string cmdText, 
CommandType type, SqlParameter[] prms)
        {
            DataTable dt = new DataTable(); 
            using (SqlConnection conn = new SqlConnection(connectionString))
            {
                conn.Open(); 
                using (SqlCommand cmd = new SqlCommand(cmdText, conn))
                {
                    cmd.CommandType = type;
                    if (prms != null)
                    {
                        foreach (SqlParameter p in prms)
                        {
                            cmd.Parameters.Add(p);
                        }
                    }
                    using (SqlDataAdapter da = new SqlDataAdapter(cmd))
                    {
                        da.Fill(dt);
                    }
                }
            }
            return dt; 
        }

        public static DataTable ExecuteDataTable(string connectionString, string cmdText, 
CommandType type)
        {
            return ExecuteDataTable(connectionString, cmdText, type, null);
        }

        public static SqlDataReader ExecuteReader(string connectionString, string cmdText, 
CommandType type, SqlParameter[] prms)
        {
            SqlConnection conn = new SqlConnection(connectionString);
            using (SqlCommand cmd = new SqlCommand(cmdText, conn))
            {
                cmd.CommandType = type;

                if (prms != null)
                {
                    foreach (SqlParameter p in prms)
                    {
                        cmd.Parameters.Add(p);
                    }
                }
                conn.Open();
                return cmd.ExecuteReader(CommandBehavior.CloseConnection);
            }
        }

        public static SqlDataReader ExecuteReader(string connectionString, string cmdText, 
CommandType type)
        {
            return ExecuteReader(connectionString, cmdText, type, null);
        }

        public static int ExecuteNonQuery(string connectionString, string cmdText, CommandType type, 
SqlParameter[] prms)
        {
            using (SqlConnection conn = new SqlConnection(connectionString))
            {
                using (SqlCommand cmd = new SqlCommand(cmdText, conn))
                {
                    cmd.CommandType = type;

                    if (prms != null)
                    {
                        foreach (SqlParameter p in prms)
                        {
                            cmd.Parameters.Add(p);
                        }
                    }
                    conn.Open();
                    return cmd.ExecuteNonQuery();
                }
            }
        }

        public static int ExecuteNonQuery(string connectionString, string cmdText, CommandType type)
        {
            return ExecuteNonQuery(connectionString, cmdText, type, null);
        }

        public static object ExecuteScalar(string connectionString, string cmdText, CommandType type,
 SqlParameter[] prms)
        {
            using (SqlConnection conn = new SqlConnection(connectionString))
            {
                using (SqlCommand cmd = new SqlCommand(cmdText, conn))
                {
                    cmd.CommandType = type;
                    if (prms != null)
                    {
                        foreach (SqlParameter p in prms)
                        {
                            cmd.Parameters.Add(p);
                        }
                    }
                    conn.Open();
                    return cmd.ExecuteScalar();
                }
            }
        }

        public static object ExecuteScalar(string connectionString, string cmdText, CommandType type)
        {
            return ExecuteScalar(connectionString, cmdText, type, null);
        }
    }
}

A classe possui os seguintes métodos:

Neste exemplo iremos usar apenas o método ExecuteDataTable() e ExecuteNonQuery().

Definindo o código da camada de apresentação

Vamos agora definir no projeto Windows Forms, formulário form1.cs, o código para exibir e persistir os dados.

A primeira coisa a fazer e incluir uma referência ao projeto DAL;

Clique com o botão direito sobre o projeto DataGridView_Basico e clique em Add Reference;

Selecione a guia Projects e marque o projeto DAL clicando no botão OK;

Após isso vamos começar declarando os namespaces usados no formulário:

using System;
using System.Data;
using System.Windows.Forms;
using System.Data.SqlClient;

Como já mencionei, não deveríamos ter uma referência a SqlClient na camada de apresentação pois essa camada não deveria ter conhecimento nenhum sobre as referências de acesso a dados.

Logo após a declaração da classe Form1 defina a variável _linhaIndice que representa o índice de uma linha do controle DataGridView;

int _linhaIndice;

No evento Load do formulário chamamos a rotina CarregaDados() que preenche o GRID:

 private void Form1_Load(object sender, EventArgs e)
 {
            CarregaDados();
}

O código da rotina CarregaDados() usa o método ExecuteDataTable() da classe SQLHelper na camada DAL e passa os parâmetros: conexão, instrução SQL e tipo de Command:

   private void CarregaDados()
   {
            try
            {
                dgvAlunos.DataSource = DAL.SQLHelper.ExecuteDataTable(DAL.SQLHelper.conection,
"Select * from Alunos", CommandType.Text);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
  }

No evento CellClick do controle DataGridView vamos incluir o código que permite selecionar os dados da linha selecionada e exibi-las nos controles de texto do formulário.

Inclua o código a seguir neste evento:

 private void dgvAlunos_CellClick(object sender, DataGridViewCellEventArgs e)
 {
            //Retorna o indice da linha no qual a célula foi clicada
            _linhaIndice = e.RowIndex;  

            //Se _linhaIndice é menor que -1 então retorna
            if (_linhaIndice == -1)
            { 
                return;
            }
            
            //Cria um objeto DataGridViewRow de um indice particular
            DataGridViewRow rowData = dgvAlunos.Rows[_linhaIndice]; 

            //exibe os valores no textbox
            txtCodigo.Text = rowData.Cells[0].Value.ToString();
            txtNome.Text = rowData.Cells[1].Value.ToString();
            txtEmail.Text = rowData.Cells[2].Value.ToString();
            txtCurso.Text = rowData.Cells[3].Value.ToString();
 }

O código do botão Incluir define os parâmetros passados para o método ExecuteNonQuery a partir do formulário e comando SQL Insert Into para incluir registros na tabela Alunos:

 private void btnIncluir_Click(object sender, EventArgs e)
 {
            if (btnIncluir.Text == "Incluir")
            {
                limpaTextBox();
                btnIncluir.Text = "Salvar";
                txtNome.Focus();
            }
            else
            {
                btnIncluir.Text = "Incluir";
                SqlParameter[] arParms = new SqlParameter[3];
                arParms[0] = new SqlParameter("@Nome", txtNome.Text);
                arParms[1] = new SqlParameter("@Email", txtEmail.Text);
                arParms[2] = new SqlParameter("@Curso", txtCurso.Text);
                string sql = "Insert Into Alunos(nome,email,curso) values(@Nome,@Email,@Curso)";

                try
                {
                    int i = DAL.SQLHelper.ExecuteNonQuery(DAL.SQLHelper.conection, sql, 
CommandType.Text, arParms);
                    CarregaDados();
                }
                catch (Exception ex)
                {
                    MessageBox.Show(" Erro :: " + ex.Message);
                }
        }
   }

O código do botão Excluir após verificarmos se um registro foi selecionado no datagridview utiliza o método ExecuteNonQuery da classe SQLHelper para excluir o registro:

 private void btnExcluir_Click(object sender, EventArgs e)
 {
            if (dgvAlunos.Rows.Count <= 0)
            {
                MessageBox.Show("Não existem dados a excluir.");
                return;
            }
            //verifica se foi selecionado um registro
            if (string.IsNullOrEmpty(txtCodigo.Text) || string.IsNullOrEmpty(txtNome.Text) || 
string.IsNullOrEmpty(txtEmail.Text) || string.IsNullOrEmpty(txtCurso.Text))
            {
                MessageBox.Show("Selecione um registro para exclusão.");
                return;
            }

            //Se rowindex é menor que um retorna pois seleção foi inválida
            if (_linhaIndice < 0)
                return;

            if (!(MessageBox.Show("Confirma a exclusão deste registro?", "Excluir registro !", 
MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes))
                return;

            //define os parametros
            SqlParameter[] arParms = new SqlParameter[1];
            arParms[0] = new SqlParameter("@Codigo", Convert.ToInt32(txtCodigo.Text));
            string sql = "Delete from Alunos Where Id = @codigo";

            try
            {
                int i = DAL.SQLHelper.ExecuteNonQuery(DAL.SQLHelper.conection, sql, 
CommandType.Text, arParms);
                CarregaDados();
            }
            catch (Exception ex)
            {
                MessageBox.Show(" Erro :: " + ex.Message);
            }
  }

O código do botão Atualizar define os parâmetros e o método SQL Update Set e usando o método ExecuteNonQuery exclui registros da tabela:

 private void btnAtualizar_Click(object sender, EventArgs e)
 {
            if (dgvAlunos.Rows.Count <= 0)
            {
                MessageBox.Show("Não existem dados a excluir.");
                return;
            }
            //verifica se foi selecionado um registro
            if (string.IsNullOrEmpty(txtCodigo.Text) || string.IsNullOrEmpty(txtNome.Text) || 
string.IsNullOrEmpty(txtEmail.Text) || string.IsNullOrEmpty(txtCurso.Text))
            {
                MessageBox.Show("Selecione um registro para exclusão.");
                return;
            }

            //Se rowindex é menor que um retorna pois seleção foi inválida
            if (_linhaIndice < 0)
                return;

            if (!(MessageBox.Show("Confirma a atualização deste registro?", "Atualizar registro !", 
MessageBoxButtons.YesNo, MessageBoxIcon.Warning) == DialogResult.Yes))
                return;

            SqlParameter[] arParms = new SqlParameter[4];
            arParms[0] = new SqlParameter("@Nome", txtNome.Text);
            arParms[1] = new SqlParameter("@Email", txtEmail.Text);
            arParms[2] = new SqlParameter("@Curso", txtCurso.Text);
            arParms[3] = new SqlParameter("@Codigo", txtCodigo.Text);
            string sql = "Update Alunos set Nome=@Nome, Email=@Email, Curso=@Curso 
Where Id=@Codigo";

            try
            {
                int i = DAL.SQLHelper.ExecuteNonQuery(DAL.SQLHelper.conection, sql, 
CommandType.Text, arParms);
                CarregaDados();
            }
            catch (Exception ex)
            {
                MessageBox.Show(" Erro :: " + ex.Message);
            }
  }

A rotina para limpar as caixas de texto possui o seguinte código:

 private void limpaTextBox()
  {
            TextBox[] tempTextBox = { txtCodigo, txtNome, txtEmail, txtCurso };
            foreach (TextBox temp in tempTextBox)
                temp.Clear();
 }

Executando o projeto e selecionando algumas linhas teremos o seguinte resultado:

Você pode fazer o que quiser com a informação acessada extraindo as linhas para um arquivo texto, um arquivo csv, etc.

Pegue o projeto completo aqui:  DataGridView_Basico.zip

        Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Veja os Destaques e novidades do SUPER DVD Visual Basic 2013 (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Mateus 6:2 Quando, pois, deres esmola, não faças tocar trombeta diante de ti, como fazem os hipócritas nas sinagogas e nas ruas, para serem glorificados pelos homens. Em verdade vos digo que já receberam a sua recompensa.

Mateus 6:3 Mas, quando tu deres esmola, não saiba a tua mão esquerda o que faz a direita;

Mateus 6:4 para que a tua esmola fique em secreto; e teu Pai, que vê em secreto, te recompensará.

Referências:


José Carlos Macoratti