Desenvolvimento - ADO.NET

Desenvolvendo uma aplicação CRUD com ADO.NET e Padrões de Projeto - Parte 1

Neste artigo faremos uma aplicação CRUD (Create,Read,Update and Delete), utilizando o ADO.NET. Iremos aprender de maneira simples e eficiente como realizar as operações fundamentais desta tecnologia que veio para facilitar a vida dos desenvolvedores .Net. O próximo passo será a melhoria desta aplicação segundo as melhores práticas de programação.

por Vitor Meriat



Vamos fazer uma aplicação CRUD (Create,Read,Update and Delete), utilizando o ADO.NET como arquitetura de acesso a dados.

 ADO.NET é uma tecnologia para acesso a dados que está integrada ao .NET Framework e oferece diversas classes que permitem realizar praticamente todas as tarefas relacionadas com o acesso e manutenção de dados.

Nosso exemplo consiste em uma cadastro de contatos onde informaremos dois campos, o nome e o email a ser persistido no banco de dados.

Abra o Visual Studio e crie um novo projeto do tipo ASP.NET Web Application com o nome Contatos conforme na figura 1.

(figura - 1)

Após a criação do projeto, sua solução deve ficar como na figura 2.

(figura - 2)


Clique com o botão direito na pasta App_Data e vá para o item Add subitem New Item. Selecione um template do tipo SQL Server Database e lhe de o nome de Banco.mdf conforme a figura 3.



(figura - 3)

Na aba Server Explorer, selecione o Banco.mdf e clique com o botão direito sobre a pasta Tables e selecione a opção New Query, executando o código da listagem 1.

CREATE TABLE Cadastro(Id int IDENTITY PRIMARY KEY, Nome nvarchar(100), Email nvarchar(100))

(listagem - 1)

A figura 4 exemplifica o processo.



(figura - 4)


Após o banco de dados criado, vamos para a interface de comunicação com o usuário conforme a listagem 2. Notem que os campos Nome e Email na área de pesquisa estão desabilitados. Isto se dá porque só utilizaremos estes campos no próximo artigo onde farei uso de Stored Procedures.

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="Contatos._Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
<title>Cadastro de Músicos</title>
<style type="text/css">
table.Tabela
{
border-collapse: collapse;
margin: 1em 0;
}
table.Tabela td
{
padding: .5em;
border: 1px solid #D2E9FF;
height: 23px;
}
</style>
</head>
<body>
<form id="form1" runat="server">
<div style="left: 0px; top: 0px">
<table width="800px" class="Tabela">
<tr>
<td colspan="2" align="center">
<span style="font-size: 16pt; color: #003399; font-family: Arial;"><strong>&nbsp;CADASTROS DE CONTATOS<br />
</strong></span>
</td>
</tr>
<tr style="height: 25px">
<td colspan="2" bgcolor="#99CCFF" align="center">
</td>
</tr>
<tr style="height: 25px">
<td>
</td>
<td>
</td>
</tr>
<tr>
<td>
&nbsp;
<asp:Label ID="Label1" runat="server" Style="font-family: Arial" Text="Nome:"></asp:Label>
</td>
<td>
<asp:TextBox ID="txtNome" runat="server" Width="250px"></asp:TextBox>
</td>
</tr>
<tr>
<td>
&nbsp;
<asp:Label ID="Label2" runat="server" Style="font-family: Arial" Text="Email:"></asp:Label>
</td>
<td>
<asp:TextBox ID="txtEmail" runat="server" Width="250px"></asp:TextBox>
</td>
</tr>
<tr>
<td>
</td>
<td>
</td>
</tr>
<tr style="height: 25px">
<td colspan="2" bgcolor="#99CCFF">
</td>
</tr>
<tr style="height: 25px">
<td>
</td>
<td>
</td>
</tr>
<tr>
<td align="center">
<asp:Button ID="btnCadastrar" runat="server" Text="Cadastrar"
Font-Names="Comic Sans MS" ForeColor="Black" Width="100px" />
</td>
<td>
<span style="color: #FF3300; font-size: 8pt; font-family: Arial">*Incluir um novo
contato.</span>
</td>
</tr>
<tr>
<td align="center">
<asp:Button ID="btnAlterar" runat="server" Text="Alterar"
Font-Names="Comic Sans MS" ForeColor="Black" Width="100px" />
</td>
<td>
<span style="color: #FF3300; font-size: 8pt; font-family: Arial">*Alterar
contato. É
necessário pesquisar o contato a ser alterado.</span>
</td>
</tr>
<tr>
<td align="center">
<asp:Button ID="btnExcluir" runat="server" Text="Excluir"
Font-Names="Comic Sans MS" ForeColor="Black" Width="100px" />
</td>
<td>
<span style="color: #FF3300; font-family: Arial; font-size: 8pt">*Excluir
contato.
É
necessário pesquisar o contato a ser excluído.</span>
</td>
</tr>
<tr>
<td colspan="2">
<table width="100%" cellpadding="0" cellspacing="0" align="center">
<tr>
<td colspan="2" align="center" bgcolor="#D2E9FF">
<span style="font-size: 10pt; color: #003399; font-family: Arial;">Pesquisar por:</span>
</td>
</tr>
<tr>
<td>
<span style="color: highlight; font-family: Comic Sans MS">
<asp:Label ID="Label3" runat="server" Style="font-family: Arial; font-size: small;"
Text="Código:"></asp:Label>
</span>
</td>
<td>
<span style="color: highlight; font-family: Comic Sans MS">
<asp:TextBox ID="txtCodigo" runat="server" Width="40px"></asp:TextBox>
</span>
</td>
</tr>
<tr>
<td>
<span style="color: highlight; font-family: Comic Sans MS">
<asp:Label ID="Label4" runat="server" Style="font-family: Arial; font-size: small;"
Text="Nome:"></asp:Label>
</span>
</td>
<td>
<span style="color: highlight; font-family: Comic Sans MS">
<asp:TextBox ID="txtNomePesquisa" runat="server" Width="200px"
Enabled="False"></asp:TextBox>
</span>
</td>
</tr>
<tr>
<td>
<span style="color: highlight; font-family: Comic Sans MS">
<asp:Label ID="Label5" runat="server" Style="font-family: Arial; font-size: small;"
Text="Email:"></asp:Label>
</span>
</td>
<td>
<span style="color: highlight; font-family: Comic Sans MS">
<asp:TextBox ID="txtEmailPesquisa" runat="server" Width="200px"
Enabled="False"></asp:TextBox>
</span>
</td>
</tr>
<tr>
<td align="center" colspan="2">
<asp:Button ID="btnPesquisar" runat="server" Text="Pesquisar"
Font-Names="Comic Sans MS" ForeColor="Black" Width="100px" />
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td bgcolor="#99CCFF" colspan="2">
</td>
</tr>
<tr>
<td colspan="2">
<asp:Label ID="lblMsg" runat="server" ForeColor="Red" Font-Names="Comic Sans MS"></asp:Label>
</td>
</tr>
<tr style="height: 25px">
<td colspan="2">
</td>
</tr>
<tr>
<td colspan="2">
<asp:GridView ID="grdContato" runat="server" AutoGenerateColumns="False" BackColor="White"
BorderColor="#CCCCCC" BorderStyle="None" BorderWidth="1px" CellPadding="3" EmptyDataText="NENHUM CONTATO CADASTRADO"
Width="100%" Font-Names="Comic Sans MS" Font-Size="Small">
<FooterStyle BackColor="White" ForeColor="#000066" />
<EmptyDataRowStyle HorizontalAlign="Center" />
<Columns>
<asp:BoundField DataField="Id" HeaderText="C&#211;DIGO" />
<asp:BoundField DataField="NOME" HeaderText="NOME" ItemStyle-HorizontalAlign="Left" />
<asp:BoundField DataField="EMAIL" HeaderText="EMAIL" ItemStyle-HorizontalAlign="Left" />
</Columns>
<RowStyle HorizontalAlign="Center" ForeColor="#000066" />
<SelectedRowStyle BackColor="#669999" Font-Bold="True" ForeColor="White" />
<PagerStyle BackColor="White" ForeColor="#000066" HorizontalAlign="Left" />
<HeaderStyle BackColor="#006699" Font-Bold="True" ForeColor="White" HorizontalAlign="Center" />
</asp:GridView>
</td>
</tr>
</table>
<br />
<br />
</div>
</form>
</body>
</html>

(listagem - 2)

Agora vamos criar a string de conexão(listagem 3) ,que será responsável por efetuar uma conexão com um banco de dados. O valor dessa propriedade varia de acordo com o tipo de banco de dados utilizado. Utilizo a palavra reservada const para especificar que o valor da variável local é constante, o que significa que ele não pode ser modificado. Isto é muito útil uma vez que será necessário informar a string de conexão toda vez que for preciso acessar o banco de dados.

Abra o arquivo Default.aspx.cs e insira o código da listagem 3.

// A string de conexão é responsável por apontar o caminho do banco. Sem esta string,
//não é possível estabelecer uma ligação entre a aplicação e o Banco de Dados.
// Uso a palavra reservada const para manter o valor da variável uma vez que a string de conexão não será alterada.

const string conex = @"Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\Banco.mdf;Integrated Security=True;User Instance=True";

(listagem - 3)

Antes de iniciarmos o uso do ADO.NET, é necessário que façamos sua referência no código(listagem - 4).

// Importando namespace
using System.Data;
using System.Data.SqlClient;

(listagem - 4)

Iremos fazer os métodos para as operações de inclusão, alteração, exclusão e pesquisa como na listagem 5.

#region Métodos internos da Classe

/// <summary>
///
Método responsável por persistir ou inserir no "DB" as informações
///
digitadas na tela pelo usuário.
/// </summary>

private void vInserirContato()
{
// início do bloco de tratameto de erro...
try
{
// Cria uma variável recebendo o nome digitado pelo usuário na tela
string nome = txtNome.Text;

// Cria uma variável recebendo o instrumento digitado pelo usuário na tela
string email = txtEmail.Text;

// Cria comando sql a ser executado no banco de dados. Esse comando
// inseri os dados digitados na tela no banco de dados

string sql = "INSERT INTO Cadastro (NOME, EMAIL) VALUES ("" + nome + "","" + email + "")";

// Cria uma variável de conexão.
SqlConnection con = new SqlConnection(conex);

// Cria uma variável de comando.
SqlCommand cmmd = new SqlCommand();

// Passo pra variável de comando o comando sql a ser executado no banco.

cmmd.CommandText = sql;

// Passo pra variável de comando a conexão com o banco.
cmmd.Connection = con;

// Abro a conexão com o banco.

con.Open();

// Como o tipo de comando que vou fazer no banco de dados é uma inserção (insert)
//vou utilizar o método ExecuteNonQuery da classe SqlCommand.
// ExecuteNonQuery = executa declarações SQL que não retornam dados, tais como INSERT, UPDATE, DELETE e SET.

cmmd.ExecuteNonQuery();

// Após executar o comando no banco de dados é SEMPRE necessário fechar a conexão com
// o banco de dados.

con.Close();

// Após eu fazer a inserção dos dados eu vou chamar o método
//para carregar o grid de Contatos para mostrar o Contato inserido.

carregaGrid();

// Chama método para limpar os campos, configurando os mesmos para uma nova inserção.
vLimpaCampos();

// Mostra a mensagem de sucesso.
lblMsg.Text = "Contato cadastrado com Sucesso!";
}
catch (Exception ex)
{
// Só vai passar aqui se houver erro.
// Ai mostra a mensagem de erro.

lblMsg.Text = "Erro ao Cadastrar Contato! " + ex.Message;
}
}

/// <summary>
///
Método responsável por alterar(update), no "DB" as informações
///
já persistidas pelos novos valores digitadas na tela pelo usuário.
/// </summary>

private void vAlterarContato()
{
try
{
// Cria uma variável recebendo o código do Contato a ser alterado
// Lembra que como o código é Inteiro (Número) é necessário fazer a conversão

int codContato = Convert.ToInt32(txtCodigo.Text);

// Recebe os novos valores para o Contato
string nome = txtNome.Text;
string email = txtEmail.Text;

// Cria comando sql a ser executado no banco de dados. Esse comando
// altera os dados de um Contato

string sql = "UPDATE Cadastro SET NOME = "" + nome + "", EMAIL = "" + email + "" WHERE Id = " + codContato;

// Cria uma variável de conexão passando como parâmetro entre parenteses
// a string de conexão criada acima. Toda vez que for necessário acessar o banco
// de dados será necessário cria uma variável de Conexão.

SqlConnection con = new SqlConnection(conex);

// Cria uma variável de comando onde irei passar o comando a ser
// executado no banco de dados e a conexão do banco de dados que nós
// já criamos acima.

SqlCommand cmmd = new SqlCommand();

// Passo pra variável de comando o comando sql a ser executado no banco que criamos acima.
cmmd.CommandText = sql;
// Passo pra variável de comando a conexão com o banco que criamos acima tbm...
cmmd.Connection = con;

// Pronto, já criamos o comando e a conexão com o banco
// Agora basta abrir a conexão com o banco de dados e executar a busca.

// Abro a conexão com o banco.

con.Open();

// Como o tipo de comando que vou fazer no banco de dados é uma atualização (update)
// vou utilizar o método ExecuteNonQuery da classe SqlCommand

cmmd.ExecuteNonQuery();

// Após executar o comando no banco de dados é SEMPRE necessário fechar a conexão com
// o banco de dados.

con.Close();

//Após eu fazer a inserção dos dados eu vou chamar o método
// para carregar o grid de Contatos para mostrar o Contato inserido.

carregaGrid();

// Chama método para limpar os campos
vLimpaCampos();

// Mostra a mensagem de alterado com sucesso
lblMsg.Text = "Contato alterado com Sucesso!";
}
catch (FormatException ex)
{
// Só vai passar aqui se houver erro
// Ai mostra a mensagem de erro no Label lblMsg

lblMsg.Text = "O Código do Contato deve ser digitado e deve ser número inteiro." + ex.Message;
}
}

/// <summary>
///
Método responsável por pesquisar(select), no "DB" as informações
///
usando como parâmetro o codigo, nome e instrumento do Contato.
/// </summary>

private void vPesquisarContato()
{
try
{

// Cria uma variável recebendo o código do músico a ser pesquisado
// Lembra que como o código é Inteiro (Número) é necessário fazer a conversão
int codContato = Convert.ToInt32(txtCodigo.Text);

// Cria comando sql a ser executado no banco de dados. Esse comando
// executa uma pesquisa no banco de dados onde (where) o código do contato for igual ao código digitado.
string sql = "SELECT * FROM Cadastro WHERE Id = " + codContato;

// Cria uma variável de conexão passando como parâmetro entre parenteses
// a string de conexão criada acima. Toda vez que for necessário acessar o banco
// de dados será necessário cria uma variável de Conexão.
SqlConnection con = new SqlConnection(conex);

// Cria uma variável de comando onde irei passar o comando a ser
// executado no banco de dados e a conexão do banco de dados que nós
// já criamos acima.
SqlCommand cmmd = new SqlCommand();

// Passo pra variável de comando o comando sql a ser executado no banco que criamos acima.
cmmd.CommandText = sql;
// Passo pra variável de comando a conexão com o banco que criamos acima tbm...
cmmd.Connection = con;

// Pronto, já criamos o comando e a conexão com o banco
// Agora basta abrir a conexão com o banco de dados e executar a busca.

// Abro a conexão com o banco.

con.Open();

// Como o tipo de comando que vou fazer é uma busca (select) no banco de dados
// vou utilizar o método ExecuteReader da classe SqlCommand para fazer a leitura
// dos dados e adicionar no GridView
// Crio uma variável SqlDataReader para fazer a leitura

SqlDataReader dr = cmmd.ExecuteReader();

// Utilizo o while para ler todos os dados encontrados.
while (dr.Read())
{
// Mostro na tela os dados encontrados
// Mostro o nome

txtNome.Text = dr["NOME"].ToString();
// Mostro o Instrumento
txtEmail.Text = dr["EMAIL"].ToString();
}

// Após executar o comando no banco de dados é SEMPRE necessário fechar a conexão com
// o banco de dados.

con.Close();

// Limpo os campos pesquisados para uma nova pesquisa.
vLimpaCampos();

// Limpo a label utilizada para mensagens.

lblMsg.Text = String.Empty;
}
catch (FormatException ex)
{
// Só vai passar aqui se houver erro
// Ai mostra a mensagem de erro no Label lblMsg

lblMsg.Text = "O Código do Contato deve ser digitado e deve ser número inteiro." + ex.Message;
}
}

/// <summary>
///
Método responsável por Excluir(delete), no "DB" as informações
///
usando como parâmetro o codigo do Contato..
/// </summary>

private void vExcluirContato()
{
try
{
// Cria uma variável recebendo o código do Contato a ser excluído
// Lembra que como o código é Inteiro (Número) é necessário fazer a conversão

int codContato = Convert.ToInt32(txtCodigo.Text);

// Cria comando sql a ser executado no banco de dados. Esse comando
// exclui o contato que possui o código digitado

string sql = "DELETE FROM CONTATO WHERE Id = " + codContato;

// Cria uma variável de conexão passando como parâmetro entre parenteses
// a string de conexão criada acima. Toda vez que for necessário acessar o banco
// de dados será necessário cria uma variável de Conexão.

SqlConnection con = new SqlConnection(conex);

// Cria uma variável de comando onde irei passar o comando a ser
// executado no banco de dados e a conexão do banco de dados que nós
// já criamos acima.

SqlCommand cmmd = new SqlCommand();

// Passo pra variável de comando o comando sql a ser executado no banco que criamos acima.
cmmd.CommandText = sql;
// Passo pra variável de comando a conexão com o banco que criamos acima tbm...
cmmd.Connection = con;

// Pronto, já criamos o comando e a conexão com o banco
// Agora basta abrir a conexão com o banco de dados e executar a busca.


// Abro a conexão com o banco.
con.Open();

// Como o tipo de comando que vou fazer no banco de dados é uma atualização (update)
// vou utilizar o método ExecuteNonQuery da classe SqlCommand

cmmd.ExecuteNonQuery();

// Após executar o comando no banco de dados é SEMPRE necessário fechar a conexão com
// o banco de dados.

con.Close();

//Após eu fazer a inserção dos dados eu vou chamar o método
// para carregar o grid de Contatos para mostrar o contato inserido.

carregaGrid();

// Chama método para limpar os campos
vLimpaCampos();

// Mostra a mensagem de excluído com sucesso
lblMsg.Text = "Contato excluído com Sucesso!";
}
catch (FormatException ex)
{
// Só vai passar aqui se houver erro
// Ai mostra a mensagem de erro no Label lblMsg

lblMsg.Text = "O Código do Contato deve ser digitado e deve ser número inteiro."
+ ex.Message;
}
}

#endregion

(listagem - 5)

Se você prestou atenção, verá que o padrão de acesso ao banco de dados é muito parecido em todas as operações realizadas.

Para darmos mais reuso ao código, vamos criar um método para carregarmos o grid e outro para limparmos os campos. Os códigos citados estão na listagem 6.

O método carregaGrid será utilizado em duas ocasiões: no Page_Load da página para que os contatos inseridos possam aparecer logo na abertura da mesma; e toda vez que for necessário atualizar os valores do grid.

/// <summary>
///
Método responsável por carregar o grid com as informações vindas
///
do banco de dados.
/// </summary>
private void carregaGrid()
{
// Cria comando sql a ser executado no banco de dados. Esse comando
// executa uma busca de todos os dados da tabela Cadastro.

string sql = "SELECT * FROM Cadastro";

// Cria uma variável de conexão que recebe como parâmetro a string de conexão.
// Toda vez que for necessário acessar o banco de dados será necessário criar
//uma variável de Conexão.
// O objeto Connection têm a função de gerar uma conexão com uma fonte de dados sendo
//portanto o objeto fundamental no acesso a dados.

SqlConnection con = new SqlConnection(conex);

// Cria a variável de comando onde irei passar o comando a ser
//executado no banco de dados.
// Os objetos Command são usados para executar declarações SQL e stored
//procedures(procedimetos armazenados).

SqlCommand cmmd = new SqlCommand();

// Passo para variável de comando o comando sql a ser executado no banco que criamos acima.
cmmd.CommandText = sql;

// Passo para variável de comando a conexão com o banco...
cmmd.Connection = con;

// Pronto, já criamos o comando e a conexão com o banco
// Agora basta abrir a conexão com o banco de dados e executar a busca.

// Abro a conexão com o banco.

con.Open();

// Como o tipo de comando que vou fazer é uma busca (select), no banco de dados
// vou utilizar o método ExecuteReader da classe SqlCommand para fazer a leitura
// dos dados e adicionar no GridView.
// ExecuteReader = executa declarações SQL que retornan linhas de dados, tais como no SELECT...

grdContato.DataSource = cmmd.ExecuteReader();
grdContato.DataBind();

// Após executar o comando no banco de dados é "SEMPRE" necessário fechar a conexão com
// o banco de dados.

con.Close();
}


/// <summary>
///
Método responsável por limpar os campos do cadastro.
/// <remarks>
///
Configura os controles para uma nova inserção.
/// </remarks>
/// </summary>

private void vLimpaCampos()
{
// Atribui uma string vazia a propriedade Text dos controles.
txtNome.Text = String.Empty;
txtCodigo.Text = String.Empty;
txtEmail.Text = String.Empty;
}

(listagem - 6)

Agora vamos dar um clique duplo nos botões de Cadastrar, Alterar, Pesquisar e Excluir chamando os métodos correspondentes para cada botão como na listagem 7.

#region Eventos dos Controles

/// <summary>
///
Método Acionado ao clicar no botão cadastrar.
/// </summary>
/// <remarks>
///
Método responsável por persistir ou inserir no "DB" as informações
///
digitadas na tela pelo usuário.
/// </remarks>
/// <param name="sender"></param>
/// <param name="e"></param>

protected void btnCadastrar_Click(object sender, EventArgs e)
{
// Método responsável por inserir um novo Contato no banco de dados.
vInserirContato();
}

/// <summary>
///
Método Acionado ao clicar no botão Alterar.
/// </summary>
/// <remarks>
///
Método responsável por alterar(update), no "DB" as informações
///
já persistidas pelos novos valores digitadas na tela pelo usuário.
/// </remarks>
/// <param name="sender"></param>
/// <param name="e"></param>

protected void btnAlterar_Click(object sender, EventArgs e)
{
// Método responsável por alterar um contato no banco de dados.
vAlterarContato();
}

/// <summary>
///
Método Acionado ao clicar no botão Pesquisar.
/// </summary>
/// <remarks>
///
Método responsável por pesquisar(select), no "DB" as informações
///
usando como parâmetro o codigo, nome e instrumento do contato.
/// </remarks>
/// <param name="sender"></param>
/// <param name="e"></param>

protected void btnPesquisar_Click(object sender, EventArgs e)
{
// Método responsável por pesquisar um contato no banco de dados.
vPesquisarContato();
}

/// <summary>
///
Método Acionado ao clicar no botão Excluir.
/// </summary>
/// <remarks>
///
Método responsável por Excluir(delete), no "DB" as informações
///
usando como parâmetro o codigo do contato..
/// </remarks>
/// <param name="sender"></param>
/// <param name="e"></param>

protected void btnExcluir_Click(object sender, EventArgs e)
{
// Método responsável por excluir um contato no banco de dados.
vExcluirContato();
}
#endregion

(listagem - 7)

Nossa aplicação está pronta para ser testada.
O próximo passo será a utilização de Desing Patterns nesta aplicação. A idéia é evoluir projeto e utilizar exemplos práticos das melhores práticas de programação.


Um abraço a todos!

Vitor Meriat

Vitor Meriat - Cusando a faculdade de Bacharel em Sistemas da Informação, programador .NET há dois anos, trabalha atualmente na Corretora Seguros BRB em Brasília com a plataforma .Net e Arquitetura da Informação.