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:

........
<
connectionStrings>

<add

    name="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 = "";


    conn =
ConfigurationManager.ConnectionStrings["FunciConnectionString"].ConnectionString;

 

    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 extensões de métodos.

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.

fonte:  ASP .NET - Usando LINQ - Expressões Lambada

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));


if
(objFunci != null
)

{

//excluir alinha

tblFunci.DeleteOnSubmit(delFunci);


//Salva as linhas modificadas

db.SubmitChanges();
 

this.lblmsg.Text = "Excluido com sucesso.";

}

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