Uma coisa essencial que um desenvolvedor precisa saber para criar uma aplicação comercial é o CRUD (Create, Read, Update e Delete) que é composto pelas operações básicas de banco de dados. E como uma aplicação comercial é baseada em cadastros sua função é muito importante nesse tipo de aplicação.

Nesse artigo será apresentado um CRUD utilizando parâmetros, mas antes é preciso conhecer o CRUD sem a utilização de parâmetros para entender por que é melhor a utilização deles.

Normalmente em uma tela de cadastro de uma aplicação são utilizadas os seguintes comandos SQL:

  • INSERT - para inserir dados.
  • SELECT - para selecionar e consultar dados.
  • UPDATE - para atualizar os dados de um cadastros.
  • DELETE - para excluir dados.

A Listagem 1 contém o código que executará um INSERT no banco de dados com os dados de um formulário sem a utilização de parâmetros, não se preocupe com o formulário agora, o importante e entender como está sendo feito a execução do INSERT.


private void btnSalvar_Click(object sender, EventArgs e)
{
  string sql = "INSERT INTO CLIENTE (NOME,ENDERECO,CEP,BAIRRO,CIDADE,
  UF,TELEFONE) "  
  + "VALUES ('" + txtNome.Text + "', '" + txtEndereco.Text + "', '" 
  + mskCep.Text + "', '" + txtBairro
  + "', '" + txtCidade.Text + "', '" + txtUf.Text + "', '" 
  + mskTelefone.Text + "')";
           
   SqlConnection con = new SqlConnection(connectionString);
   SqlCommand cmd = new SqlCommand(sql, con);
   cmd.CommandType = CommandType.Text;
   con.Open();
   try
    {
       int i = cmd.ExecuteNonQuery();
       if (i > 0)
        MessageBox.Show("Cadastro realizado com sucesso!");
      }
     catch (Exception ex)
     {
        MessageBox.Show("Erro: " + ex.ToString());
      }
      finally
      {
        con.Close();
      }
}
Listagem 1. INSERT sem parâmetros

Ao observar o código é possível notar que ele está utilizando os dados do formulário para montar a instrução SQL a ser executada e assim inseri-los no banco. A utilização de parâmetros traz proteção para uma prática chamada SQL Injection que consiste em um usuário mal intencionado digitar um código SQL no TextBox, como uma instrução de DELETE e prejudicar o banco de dados, já que o código da aplicação está utilizando o texto no TextBox para montar a instrução SQL o que o usuário digitar fará parte desta instrução.

Quando se utiliza parâmetros a instrução SQL, esta fica mais segura contra SQL Injection e por isso é a maneira recomendável de se trabalhar.

Agora será desenvolvido uma tela de cadastro para a demonstração da utilização de parâmetros.

Será usado uma tela de cadastro e um banco de dados de exemplo para entendimento e para o desenvolvimento, será usado C# com Visual Studio 2012 e SQL Server 2012 do mesmo. Para melhor compreensão deste artigo será necessário um conhecimento prévio de SQL, C#.

A Listagem 2 contém o código necessário para a criação do banco de dados e tabela do exemplo.


/* CRIAR BANCO DE DADOS */
  CREATE DATABASE BDCADASTRO
   
  /* SELECIONA O BANCO DE DADOS */
  USE BDCADASTRO
   
  /* CRIACÇÃO DA TABELA */
  CREATE TABLE CLIENTE (
        ID INT NOT NULL IDENTITY,
        NOME VARCHAR(50)  NOT NULL,
        ENDERECO VARCHAR(50),
        CEP VARCHAR(9),
        BAIRRO VARCHAR(50),
        CIDADE VARCHAR(50),
        UF VARCHAR(2),
        TELEFONE VARCHAR(15),
        CONSTRAINT PK_CLIENTE PRIMARY KEY(ID) 
)
Listagem 2. Comandos SQL para criação do banco e tabela

Crie um formulário conforme a Figura 1.

Tela de cadastro
Figura 1. Tela de cadastro

Crie os campos conforme a Tabela 1.

Campos Propriedades
Cadastro de cliente Tipo: Form
Name: frmCadastroCliente
StartPosition: CenterScreen
Id Tipo: TextBox
Name: txtId
ReadOnly: True
Nome Tipo: TextBox
Name: txtNome
CharacterCasing: Upper
MaxLength: 50
Endereço Tipo: TextBox
Name: txtEndereco
CharacterCasing: Upper
MaxLength: 50
CEP Tipo: MaskedTextBox
Name: mskCEP
Mask: 00000-999
Bairro Tipo: TextBox
Name: txtBairro
CharacterCasing: Upper
MaxLength: 50
Cidade Tipo: TextBox
Name: txtCidade
CharacterCasing: Upper
MaxLength: 50
UF Tipo: TextBox
Name: txtUf
CharacterCasing: Upper
MaxLength: 2
Telefone Tipo: MaskedTextBox
Name: mskTelefone
Mask: (99) 0000-0000
Barra de botões Tipo: ToolStrip
Name: toolStrip1
Novo Tipo: ToolStripButton
Name: tsbNovo
Text: Novo
Salvar Tipo: ToolStripButton
Name: tsbSalvar
Text: Salvar
Cancelar Tipo: ToolStripButton
Name: tsbCancelar
Text: Cancelar
Excluir Tipo: ToolStripButton
Name: tsbExcluir
Text: Excluir
Separador Tipo: ToolStripSeparator
Name: toolStripSeparator1
Buscar por Id: Tipo: ToolStripLabel
Name: tsbBuscaPorId
Text: Buscar por Id:
Tipo: ToolStripTextBox
Name: tstId
Buscar Tipo: ToolStripButton
Name: tsbBuscar
Text: Buscar
Tabela 1. Campos do formulário

As imagens para os botões podem ser encontradas no site IconFider, basta apenas procurar pelo nome.

Dê dois cliques em uma área vazia do formulário, será mostrado o arquivo frmCadastroCliente.cs e será criado o método frmCadastroCliente_Load. Logo acima do método frmCadastroCliente_Load existe o construtor da classe que é o frmCadastroCliente e acima deste, crie as seguintes variáveis conforme a Listagem 3.


string connectionString = @"Server=.;Database=bdcadastro;Trusted_Connection=True;";
bool novo;
  
   
public frmCadastroCliente()
 {
   InitializeComponent();
 }
   
private void frmCadastroCliente_Load(object sender, EventArgs e)
{
   
}
Listagem 3. Criação das variáveis

A variável connectionString armazena a string de conexão com o banco de dados e a variável novo será usada para quando salvar saber se o que será salvo é um novo registro ou uma atualização de um registro existente.

Quando o programa for executado alguns campos deverão aparecer desabilitados e só serão habilitados ao clicar no botão Novo, permitindo assim digitar as informações, e também alguns botões da barra também estarão inacessíveis e serão habilitados conforme a situação. Essas mudanças de estado ocorrerão a cada evento, o método frmCadastroCliente_Load é executado ao carregar o formulário e para obter a configuração inicial do formulário insira o seguinte código no método, conforme mostra a Listagem 4.


private void frmCadastroCliente_Load(object sender, EventArgs e)
{
   tsbNovo.Enabled = true;
   tsbSalvar.Enabled = false;
   tsbCancelar.Enabled = false;
   tsbExcluir.Enabled = false;
   tstId.Enabled = true;
   tsbBuscar.Enabled = true;
   txtNome.Enabled = false;
   txtEndereco.Enabled = false;
   mskCep.Enabled = false;
   txtBairro.Enabled = false;
   txtCidade.Enabled = false;
   txtUf.Enabled = false;
   mskTelefone.Enabled = false;
}
Listagem 4. Configuração inicial do formulário

Agora a Listagem 5 mostra o código do botão Novo.


private void tsbNovo_Click(object sender, EventArgs e)
{
 tsbNovo.Enabled = false;
 tsbSalvar.Enabled = true;
 tsbCancelar.Enabled = true;
 tsbExcluir.Enabled = false;
 tstId.Enabled = false;
 tsbBuscar.Enabled = false;
 txtNome.Enabled = true;
 txtEndereco.Enabled = true;
 mskCep.Enabled = true;
 txtBairro.Enabled = true;
 txtCidade.Enabled = true;
 txtUf.Enabled = true;
 mskTelefone.Enabled = true;
 txtNome.Focus();
 novo = true;
}
Listagem 5. Código do botão Novo

Pode-se notar que a última linha de código está sendo atribuído true para a variável novo, mais adiante será possível entender melhor que isso significa que ao clicar no botão Novo será incluído um novo registro.

A Listagem 6 contém com o código do botão Salvar.


private void tsbSalvar_Click(object sender, EventArgs e)
{
  if (novo)
  {
     string sql = "INSERT INTO CLIENTE (NOME,ENDERECO,CEP,BAIRRO,CIDADE,
     UF,TELEFONE) " +
     "VALUES (@Nome, @Endereco, @Cep, @Bairro, @Cidade, @Uf, @Telefone)";
   
     SqlConnection con = new SqlConnection(connectionString);
     SqlCommand cmd = new SqlCommand(sql, con);
     cmd.Parameters.AddWithValue("@Nome", txtNome.Text);
     cmd.Parameters.AddWithValue("@Endereco", txtEndereco.Text);
     cmd.Parameters.AddWithValue("@Cep", mskCep.Text);
     cmd.Parameters.AddWithValue("@Bairro", txtBairro.Text);
     cmd.Parameters.AddWithValue("@Cidade", txtCidade.Text);
     cmd.Parameters.AddWithValue("@Uf", txtUf.Text);
     cmd.Parameters.AddWithValue("@Telefone", mskTelefone.Text);
     cmd.CommandType = CommandType.Text;
     con.Open();
  
     try
     {
        int i = cmd.ExecuteNonQuery();
        if (i > 0)
         MessageBox.Show("Registro incluido com sucesso!");
     }
     catch (Exception ex)
     {
        MessageBox.Show("Erro: " + ex.ToString());
      }
      finally
      {
         con.Close();
      }
   }
   else
   {
     string sql = "UPDATE CLIENTE SET NOME=@Nome, ENDERECO=@Endereco, 
     CEP=@Cep, BAIRRO=@Bairro, " +
     "CIDADE=@Cidade, UF=@Uf, TELEFONE=@Telefone WHERE ID=@Id";
     SqlConnection con = new SqlConnection(connectionString);
     SqlCommand cmd = new SqlCommand(sql, con);
    cmd.Parameters.AddWithValue("@Id", txtId.Text);
    cmd.Parameters.AddWithValue("@Nome", txtNome.Text);
    cmd.Parameters.AddWithValue("@Endereco", txtEndereco.Text);
    cmd.Parameters.AddWithValue("@Cep", mskCep.Text);
    cmd.Parameters.AddWithValue("@Bairro", txtBairro.Text);
    cmd.Parameters.AddWithValue("@Cidade", txtCidade.Text);
    cmd.Parameters.AddWithValue("@Uf", txtUf.Text);
    cmd.Parameters.AddWithValue("@Telefone", mskTelefone.Text);
    cmd.CommandType = CommandType.Text;
    con.Open();
    try
    {
       int i = cmd.ExecuteNonQuery();
       if (i > 0)
        MessageBox.Show("Registro atualizado com sucesso!");
    }
     catch (Exception ex)
    {
        MessageBox.Show("Erro: " + ex.ToString());
     }
     finally
     {
        con.Close();
     }
   }
   tsbNovo.Enabled = true;
   tsbSalvar.Enabled = false;
   tsbCancelar.Enabled = false;
   tsbExcluir.Enabled = false;
   tstId.Enabled = true;
   tsbBuscar.Enabled = true;
   txtNome.Enabled = false;
   txtEndereco.Enabled = false;
   mskCep.Enabled = false;
   txtBairro.Enabled = false;
   txtCidade.Enabled = false;
   txtUf.Enabled = false;
   mskTelefone.Enabled = false;
   txtId.Text = "";
   txtNome.Text = "";
   txtEndereco.Text = "";
   mskCep.Text = "";
   txtBairro.Text = "";
   txtCidade.Text = "";
   txtUf.Text = "";
   mskTelefone.Text = "";
}
Listagem 6. Código do botão salvar

Neste código há um if que testa o valor da variável novo para saber se é um registro novo e executa o código.

Quando novo=true a variável sql que é uma string recebe uma instrução SQL de INSERT que está sendo montada com seu parâmetros e depois cada parâmetro recebe o valor de um campo.

Logo após é criado um objeto com o tipo SqlConnection que é a conexão com o banco e que recebe como parâmetro no momento da instanciação a variável connectionString que foi criada anteriormente e que contém a string de conexão.

Depois é criado o objeto cmd que é um SqlCommand que recebe como parâmetro no seu construtor a variável sql que contém a instrução SQL e o objeto con que é a conexão. Depois é atribuído um valor para cada parâmetro da instrução SQL.

O objeto cmd será responsável por executar a instrução SQL.

Depois é definido o tipo de comando do objeto cmd, no caso Text, logo em seguida é aberta a conexão.

Dentro do bloco try é executada a instrução SQL do objeto cmd através do método ExecuteNonQuery que retorna o número de linha afetadas, que no caso é armazenada na variável inteira i.

Logo após testa-se se o valor de i é maior que 0, se sim o registro foi incluído com sucesso.

Voltando um pouco, se quando o if testa a variável novo e for false executa o código contido no bloco else o que significa que está fazendo uma atualização de um registro.

O código é praticamente o mesmo, a não ser pela instrução SQL que agora é um UPDATE.

Logo depois é alterado o estado dos controles do formulário novamente.

A Listagem 7 contém o código do botão Cancelar, que só é alterado o estado dos controles e limpa os TextBox’s.


private void tsbCancelar_Click(object sender, EventArgs e)
{
   
  tsbNovo.Enabled = true;
  tsbSalvar.Enabled = false;
  tsbCancelar.Enabled = false;
  tsbExcluir.Enabled = false;
  tstId.Enabled = true;
  tsbBuscar.Enabled = true;
  txtNome.Enabled = false;
  txtEndereco.Enabled = false;
  mskCep.Enabled = false;
  txtBairro.Enabled = false;
  txtCidade.Enabled = false;
  txtUf.Enabled = false;
  mskTelefone.Enabled = false;
  txtId.Text = "";
  txtNome.Text = "";
  txtEndereco.Text = "";
  mskCep.Text = "";
  txtBairro.Text = "";
  txtCidade.Text = "";
  txtUf.Text = "";
  mskTelefone.Text = "";
   
}
Listagem 7. Código do botão Cancelar

A Listagem 8 mostra o código do botão Excluir, que é bem parecido ao do botão Salvar, só que agora com a instrução de DELETE.


private void tsbExcluir_Click(object sender, EventArgs e)
{
   
  string sql = "DELETE FROM CLIENTE WHERE ID=@Id";
  SqlConnection con = new SqlConnection(connectionString);
  SqlCommand cmd = new SqlCommand(sql, con);
  cmd.Parameters.AddWithValue("@Id", txtId.Text);
  cmd.CommandType = CommandType.Text;
  con.Open();
  
  try
   {
     int i = cmd.ExecuteNonQuery();
     if (i > 0)
      MessageBox.Show("Registro excluído com sucesso!");
     }
     catch (Exception ex)
     {
        MessageBox.Show("Erro: " + ex.ToString());
     }
     finally
     {
        con.Close();
      }
       
      tsbNovo.Enabled = true;
      tsbSalvar.Enabled = false;
      tsbCancelar.Enabled = false;
      tsbExcluir.Enabled = false;
      tstId.Enabled = true;
      tsbBuscar.Enabled = true;
      txtNome.Enabled = false;
      txtEndereco.Enabled = false;
      mskCep.Enabled = false;
      txtBairro.Enabled = false;
      txtCidade.Enabled = false;
      txtUf.Enabled = false;
      mskTelefone.Enabled = false;
      txtId.Text = "";
      txtNome.Text = "";
      txtEndereco.Text = "";
      mskCep.Text = "";
      txtBairro.Text = "";
      txtCidade.Text = "";
      txtUf.Text = "";
      mskTelefone.Text = "";
}
Listagem 8. Código do botão Excluir

A Listagem 9 mostra o código do botão Buscar.


private void tsbBuscar_Click(object sender, EventArgs e)
 {
    string sql = "SELECT * FROM CLIENTE WHERE ID=@Id";
 
    SqlConnection con = new SqlConnection(connectionString);
    SqlCommand cmd = new SqlCommand(sql, con);
    cmd.Parameters.AddWithValue("@Id", tstId.Text);
    cmd.CommandType = CommandType.Text;
    SqlDataReader reader;
    con.Open();
    try
   {
       reader = cmd.ExecuteReader();
       if (reader.Read())
       {
           tsbNovo.Enabled = false;
           tsbSalvar.Enabled = true;
           tsbCancelar.Enabled = true;
           tsbExcluir.Enabled = true;
           tstId.Enabled = false;
           tsbBuscar.Enabled = false;
           txtNome.Enabled = true;
           txtEndereco.Enabled = true;
           mskCep.Enabled = true;
           txtBairro.Enabled = true;
           txtCidade.Enabled = true;
           txtUf.Enabled = true;
           mskTelefone.Enabled = true;
           txtNome.Focus();
           txtId.Text = reader[0].ToString();
           txtNome.Text = reader[1].ToString();
           txtEndereco.Text = reader[2].ToString();
           mskCep.Text = reader[3].ToString();
           txtBairro.Text = reader[4].ToString();
           txtCidade.Text = reader[5].ToString();
           txtUf.Text = reader[6].ToString();
            mskTelefone.Text = reader[7].ToString();
            novo = false;
      }
      else
       MessageBox.Show("Nenhum registro encontrado com o Id informado!");
    }
    catch (Exception ex)
    {
        MessageBox.Show("Erro: " + ex.ToString());
     }
     finally
     {
       con.Close();
      }
   
      tstId.Text = "";
   
}
Listagem 9. Código do botão Buscar

No código do botão Buscar contém uma instrução de SELECT que retorna o registro com o Id informado.

Uma diferença é que além do objeto cmd agora também há um objeto reader do tipo SqlDataReader que armazena o conteúdo retornado da consulta, como é mostrado na Listagem 10.


reader = cmd.ExecuteReader();
Listagem 10. Objeto reader recebendo o resultado da consulta executada pelo objeto cmd

Em seguida o if testa se há registro no reader com o método Read, se sim, executa o bloco.

O que há de diferente é que logo após alterar os estados dos controles o foco do cursor é posicionado no campo txtNome através do método Focus e é atribuído a cada campo o valor correspondente que está no reader.

Para acessar os campos no reader é utilizado o índice do campo, esse índice é a ordem dos campos, para poder vê-los basta executar um SELECT no SQL Server Management Studio e verificar o retorno, o primeiro campo inicia no índice 0.

Foi demonstrado neste artigo como criar um CRUD utilizando parâmetros ao invés de concatenar os valores dos campos com as string de instrução SQL, esta é uma maneira mais segura e otimizada de executar instruções SQL.

Qualquer dúvida é só entrar em contato.