ASP .NET - Usando LINQ para manutenção de dados II (C#)
Nesta segunda parte do meu artigo ASP .NET - Usando LINQ to SQL para manutenção de dados (C#) vamos prosseguir realizando agora as operações de manutenção de dados usando LINQ to SQL e o Visual Web Developer 2008 Express com C#.
Nota: "Se você desconhece os conceitos sobre LINQ sugiro que leia os artigos da seção LINQ no site" ( LINQ )
Este artigo é essencialmente prático e mostra como realizar a manutenção de dados em uma aplicação ASP .NET usando LINQ to SQL e C#.
Vamos abrir o web site LINQManutencaoDados criado na primeira parte deste artigo usando o Visual Web Developer 2008 Express Edition e no menu WebSite clicar na opção Add New Item e selecionar o template Web Form informando o nome Manutencao.aspx. (Marque a opção Place code in separate File e verifique se o item Language esta definido como C#);
A seguir vamos incluir, a partir da ToolBox, no formulário web Manutencao.aspx os seguintes componentes:
Defina o seguinte leiaute no formulário :
O leiaute foi definido usando tabelas. No menu Table -> Insert Table , inclua uma tabela com 3 linhas ( Rows =3) e 2 colunas (Columns=2) e clique em OK;
Selecione as duas últimas linhas e no menu Table na opção Modify selecione Merge Cells; Desta forma as duas últimas linhas serão mescladas conforme a figura abaixo:
Agora em cada linha da tabela acima vamos incluir os controles usados definidos , sendo que na primeira linha e coluna vamos incluir uma nova tabela com 4 linhas e duas colunas (Menu Table->Insert Table) onde iremos definir em uma coluna os nomes dos campos e na outra incluir os controles TextBox:
Nota: Eu poderia ter usado um controle DetailsView para incluir, editar e deletar registros mas preferi mostrar uma outra opção mais simples para fazer o trabalho.
Para encerrar a definição do leiaute vamos incluir um novo controle Button (ID=btnProcurar) ao lado do TextBox txtID conforme a figura abaixo:
Agora que já temos o leiaute definido vamos partir para codificar os respectivos eventos de cada um dos controles do formulário web no arquivo code-behind manutencao.aspx.cs;
Antes de começar vamos criar uma nova classe para que possamos obter a conexão.O objetivo é criar um data context fortemente tipado onde a nossa classe vai derivar da classe base DataContext.
No menu WebSite selecione Add New Item e selecione o template Class informando o nome FunciDataContext.cs;
A seguir inclua o seguinte código nessa classe:
using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Data.Linq;/// <summary>/// Classe com construtor que aceita uma string de conexÆo com/// o banco de dados e a passa para a classe base./// </summary>public class FunciDataContext : DataContext{ public FunciDataContext(string connectionString): base(connectionString) { } public Table<Funci> Funcionarios; }
|
Agora vamos voltar ao code-behind do formulário.
A primeira declaração que temos que fazer é a definição dos seguintes namespace :
using
System.Data.Linq;
using
System.Configuration;
No formulário vamos definir uma a string conn que irá receber a string de
conexão:
String
conn;A seguir vamos definir a string de conexão no arquivo web.config. Para isso definimos os valores no elemento <connectionStrings> do arquivo Web.Config conforme abaixo:
........ < addname="FunciConnectionString" connectionString=".\SQLEXPRESS;AttachDbFilename=C:\dados\Cadastro.mdf;Integrated Security=True;Connect Timeout=30;User Instance=True" providerName="System.Data.SqlClient" /> </ connectionStrings>........... |
Bem, para ler o valor definido no arquivo web.config usamos o seguinte código no evento Load da página:
protected void Page_Load(object sender, EventArgs e){ lblmsg.Text = "";
if (conn == null || string.IsNullOrEmpty(conn)) { lblmsg.Text ="A string de conexÆo nÆo foi definida."; } } |
No código obtemos o valor da string de conexão e verificamos se o mesmo não é null ou vazio.
Vejamos o código do botão Selecionar que irá exibir os dados no GridView - gdvFuncis:
protected
void
btnSelecionar_Click(object
sender, EventArgs
e)
{ DataContext db = new FunciDataContext(conn);
Table<Funci> tblFunci = db.GetTable<Funci>();
this.gdvFuncis.DataSource = tblFunci; this.gdvFuncis.DataBind(); }
|
Criamos uma instância do DataContext passando a string de conexão definida para o construtor da classe FunciDataContext() definido na classe FunciDataContext.
Em seguida obtemos os valores da tabela Funcionarios e exibimos no gridview.
No evento click do botão - btnProcurar - temos o seguinte código:
protected void btnProcurar_Click(object sender, EventArgs e){ if (txtID.Text.Equals("") || txtID.Text == null || txtID.Text== string.Empty) { this.lblmsg.Text = "Informe o código do funcionário"; } else { try { DataContext db = new FunciDataContext(conn); //Obtem a tabela Table<Funci> tblFunci = db.GetTable<Funci>(); //Obtem uma linha existente na tabela Funci oFunci = tblFunci.SingleOrDefault(p => p.funciID => Int32.Parse(this.txtID.Text)); if (oFunci != null) { this.txtNome.Text = oFunci.Nome; this.txtSalario.Text = Convert.ToString(oFunci.Salario); this.txtSetor.Text = Convert.ToString(oFunci.setorID); } else { this.lblmsg.Text = "Funcionário não localizado."; this.txtNome.Text = ""; this.txtSalario.Text =""; this.txtSetor.Text = ""; } } catch (Exception ex) { this.lblmsg.Text = ex.Message; } } } |
Neste código primeiro verificamos se foi informado um valor para o código do funcionário.
Em seguida , caso valor tenha sido informado, criamos uma instância do datacontext , obtemos a tabela Funcionarios e usamos a seguinte expressão LINQ para retornar uma linha existente na tabela:
Funci oFunci = tblFunci.SingleOrDefault(p => p.funciID => Int32.Parse(this.txtID.Text));
Vemos ai uma expressão lambada onde usamos o método SingeOrDefault para retornar um único , e específico elemento de uma sequência de valores ou um valor padrão se o elemento não foi encontrado. A expressão procura na tabela o funcionário com o código informado no textbox txtID;
O que são Expressões Lambda ? As expressões lambda foram incluídas no VS/VB 2008 para dar suporte a consultas LINQ. As cláusulas Where são assim compiladas como expressões lambdas e chamadas em itens aplicáveis do seu dataset. Podem ser consideradas uma forma de delegate que pode passar ou retornar outra função. Nota: Delegates permitem que uma classe use métodos de outra classe. Para saber mais sobre delegates leia o meu artigo: Usando Delegates No LINQ as expressões lambda são usadas para realizar ações sobre listas de objetos e com métodos de extensão. Uma expressão lambda é então uma função sem nome que calcula e retorna um valor único e podem ser usadas em qualquer lugar que um tipo delegate for válido. |
Se o funcionário com o código foi localizado os valores serão exibidos nos controles TextBox do formulário, caso contrário será exibido um aviso ao usuário.
Para incluir um novo funcionário temos o seguinte código no evento Click do botão Novo:
protected
void btnNovo_Click(object
sender, EventArgs
e)
{ try{ DataContext db = new FunciDataContext(conn);
//Obt‚m a tabela Table<Funci> tblFunci = db.GetTable<Funci>();//incluindo uma nova linha Funci novoFunci = new Funci { funciID = Int32.Parse(this.txtID.Text), Nome = this.txtNome.Text, Salario = Decimal.Parse(this.txtSalario.Text), setorID = Int32.Parse(this.txtSetor.Text) };tblFunci.InsertOnSubmit(novoFunci); //salva as linhas incluidas db.SubmitChanges(); this.lblmsg.Text = "Incluido com sucesso."; } catch (Exception ex) { this.lblmsg.Text = ex.Message; } } |
No código acima após definirmos valores para um novo funcionário estamos usando dois métodos LINQ:
- InsertOnSubmit() - Este método adiciona uma entidade , no caso a entidade novoFunci que é do tipo Funci, em um estado pendente de inclusão a tabela Funcionarios.
- SubmitChanges() - Este método efetiva a inclusão atual feita pelo InsertOnSubmit() na tabela do banco de dados. Deve ser chamado após o método InsertOnSubmit();
A seguir vejamos o código do botão - Editar - que é responsável por realizar alterações nos dados existentes:
protected
void txtEditar_Click(object
sender, EventArgs
e)
{ try{ DataContext db = new FunciDataContext(conn);//Obt‚m a tabela Table<Funci> tblFunci = db.GetTable<Funci>();//Obt‚m uma linha existente na tabela Funci altFunci = tblFunci.SingleOrDefault(p => p.funciID => Int32.Parse(this.txtID.Text));if (altFunci != null) { //modifica a linha altFunci .Nome = this.txtNome.Text;altFunci .Salario = Decimal.Parse(this.txtSalario.Text);altFunci .setorID = Int32.Parse(this.txtSetor.Text);//salva as linha modificadas db.SubmitChanges(); this.lblmsg.Text = "Atualizado com sucesso."; } else this.lblmsg.Text = "Funcion rio nÆo localizado.";} catch (Exception ex){ this.lblmsg.Text = ex.Message;} }
|
Para alterar um valor existente para um funcionário obtemos o registro para o código do funcionário no campo txtID usando a expressão lambda e após efetuar as alterações usamos o método SubmitChanges() para efetivá-las no banco de dados.
Para excluir um registro da tabela Funcionários temos o seguinte código no evento Click do botão Deletar:
protected
void txtDeletar_Click(object
sender, EventArgs
e)
{ try{ DataContext db = new FunciDataContext(conn);//Obt‚m a tabela Table<Funci> tblFunci = db.GetTable<Funci>(); //Obt‚m uma linha existente na tabela Funci delFunci = tblFunci.SingleOrDefault(p => p.funciID=> Int32.Parse(this.txtID.Text));
{ //excluir alinha tblFunci.DeleteOnSubmit(delFunci); //Salva as linhas modificadas db.SubmitChanges(); } else this.lblmsg.Text = "Funcion rio nÆo localizado.";} catch (Exception ex){ this.lblmsg.Text = ex.Message;} }
|
O código acima usa o método DeleteOnSubmit para colocar uma entidade da tabela em estado pendente de exclusão.(Entidades desconectadas devem ser anexadas antes de poderem ser excluídas.)
Em seguida temos que chamar o método SubmitChanges para efetivar a exclusão do banco de dados.
E com isso temos definidas as operações básicas para inclui, alterar e excluir informações de uma tabela de um banco de dados usando LINQ to SQL.
Note que o código não usamos nenhuma instrução SQL , elas foram substituídas pelas expressões LINQ que estão mais próximas da linguagem usada no projeto. Perceba também que não nos preocupamos em criar objetos para gerenciar conexões nem objetos para tratar os dados como datareader, dataset , dataadapter, etc.
Abaixo temos uma visão do web site em execução:
Embora o exemplo seja bem simples vimos que usando LINQ podemos ter um ganho de produtividade com menos código e menos código significa menos erros.
É claro que o exemplo aplica-se a um banco de dados SQL Server para usarmos outros banco de dados teríamos que usar o LINQ to Entities.
O objetivo foi mostrar que usando LINQ temos novas possibilidades que podem ser exploradas.
Pegue o projeto completo (sem a base de dados) aqui : LINQManutencaoDados.zip
Até o próximo artigo LINQ.
Referências:
José Carlos Macoratti