September 2009 - Posts
Como vocês já devem ter percebido, a linguagem LINQ é muito semelhante a uma query SQL e essa tem sido uma das grandes vantagens do LINQ.
Nesse post vamos explorar mais um desses recursos, a utilização de JOIN entre duas tabelas em uma consulta e faremos o bind do resultado em um gridView do ASP.NET
Crie uma nova página ListarTodosProdutos.aspx e desenhe o leiaute como da seguinte forma:

Em seguida, clique duas vezes sobre o form e codifique o evento Page_Load() conforme o código abaixo:
protected void Page_Load(object sender, EventArgs e)
{
BlogLinqDemoDataContext db = new BlogLinqDemoDataContext();
var query = from p in db.Produtos
join c in db.CategoriaProdutos on p.CategProdID equals c.CategProdID
select new {
ID = p.ProdutoID,
Produto = p.Descricao,
Categoria = c.Descricao };
GridView1.DataSource = query;
GridView1.DataBind();
}
Veja que a query do LINQ é muito parecida com uma query T-SQL. É feito uma query na tabela de Produtos com um JOIN com a tabela de CategoriaProdutos a fim de recuperar a descrição da Categoria. Em seguida o select new determina quais campos serão selecionados e inclusive escolhendo alias para cada campo. Ao efetuar o bind no GridView, é possível ver a execução conforme tela abaixo:

Outros tipos de JOINS
No exemplo acima executamos o conhecido INNER JOIN, mas é claro que poderíamos executar outros tipos de join como LEFT JOIN, RIGHT JOIN, etc. Veja os próximos exemplos:
LEFT JOIN
var query = from produtos in db.Produtos
join categorias in db.CategoriaProdutos on produtos.CategProdID equals categorias.CategProdID into x
from categorias in x.DefaultIfEmpty()
select new {
ID = produtos.ProdutoID,
Produto = produtos.Descricao,
Categoria = categorias.Descricao };
No exemplo acima são exibidos todos os produtos que possuam ou não categorias relacionadas. No caso dos produtos sem categoria, retorna NULL. Coloquei sublinhando o que difere de um INNER JOIN que é o fato de atribuir o relacionamento à um objeto que dei o nome de "x" e depois informar que a tabela de CategoriaProdutos é DefaultIfEmpty() informando que se não houver categoria o Produto sera exibido da mesma forma.
RIGHT JOIN
var query = from produtos in db.Produtos.DefaultIfEmpty()
join categorias in db.CategoriaProdutos on produtos.CategProdID equals categorias.CategProdID into x
from prod in x
select new {
ID = prod.CategProdID,
Categoria = prod.Descricao};
No exemplo acima são exibidos todos as categorias que possuam produtos relacionadas. O resultado dessa query será esse:

No próximo post dessa série, vou mostrar como executar querys utilizando recursos de GROUP, SELECT IN e outros.
Até lá
Em continuação à série LINQ to SQL, nesse post veremos como fazer query dos dados em banco e o bind diretamente em controles ASP.NET. Nesse exemplo iremos:
- Codificar o método que retornará um objeto produto;
- Codificar o preenchimento do objeto na UI
Query em registros únicos
Na classe beProduto.cs crie o método para recuperar um produto específico. Segue abaixo o código:
public Produto RecuperarProduto(int idProduto)
{
BlogLinqDemoDataContext bd = new BlogLinqDemoDataContext();
try
{
Produto oProduto = bd.Produtos.Single(p => p.ProdutoID == idProduto);
return oProduto;
}
catch (InvalidOperationException)
{
throw new ApplicationException("Produto não encontrado !");
}
}
Com apenas 3 linhas de código é possível fazer a recuperação do objeto. Veja que se o objeto não foi localizado, o .net dispara uma exceção do tipo InvalidOperationException que poderá ser tratada e exibida a mensagem de produto inexistente.
Antes mesmo de eu explicar todos vocês já deviam ter adivinhado, inclusive no post anterior, que estamos fazendo uma query na tabela de Produtos pois o código é muito intuitivo. Essa é a idéia do LINQ, fazer ser simples algo que antes costumava dar um trabalho que sempre era repetitivo.
Em seguida, codifique a UI para recuperar e exibir o objeto:
protected void btBuscar_Click(object sender, EventArgs e)
{
beProduto beoProduto = new beProduto();
try
{
Produto oProduto = beoProduto.RecuperarProduto(Convert.ToInt32(txtCodigoProduto.Text));
txtDescricao.Text = oProduto.Descricao;
txtValor.Text = oProduto.Valor.ToString("N");
ddlCategoria.SelectedValue = oProduto.CategProdID.ToString();
}
catch (Exception ex)
{
lblerro.Text = ex.Message;
}
}
Dessa forma é possível fazer a recuperação do objeto e exibição dele nos controles. Veja que para acessar a categoria do produto eu fiz acesso à propriedade CategProdID do objeto Produto.
Fiquem atentos com a continuidade dessa série e execute os exemplos passo-a-passo pois é a melhor forma de aprender, fazendo na prática :)
Até o próximo post e aguardo comentários 
Continuando a série LINQ to SQL , nesse post iremos incluir um registro de Produto na Base de Dados SQL Server utilizando LINQ.
Crie uma nova página por nome /LINQ/Cadastro.aspx e desenho seu layout conforme mostra figura abaixo:

Após a criação da Página, crie duas classes na pasta App_Code do seu WebSite por nomes beProduto.cs e beCategoriaProduto.cs
Codifique a classe beProduto.cs conforme mostra o código abaixo:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
/// <summary>
/// Summary description for beProduto
/// </summary>
public class beProduto
{
public beProduto()
{
//
// TODO: Add constructor logic here
//
}
public void GravarProduto(Produto oProduto)
{
BloqLinqDemoDataContext bd = new BloqLinqDemoDataContext();
bd.Produtos.InsertOnSubmit(oProduto);
bd.SubmitChanges();
}
}
Veja que é criado um método que recebe um objeto do tipo Produto por parâmetro. Essa classe Produto é a própria classe criada pelo LINQ no momento da modelagem.
O objeto bd representa a conexão com o banco de dados e é representado também pela classe BlogLinqDemoDataContext. Se você abrir a classe BlogLinqDemoDataContext vai ver que o construtor padrão acessa a chave de conexão no web.config. O método InsertOnSubmit() configura uma operação de INSERT na query que será montada pelo LINQ, Já o método SubmitChanges() executa no banco de dados todas as operações processadas pelo LINQ que você tenha programado. Isso quer dizer que você pode executar diversas operações (INSERT, UPDATE, DELETE) e enviar as alterações de uma só vez para o banco de dados através do método SubmitChanges().
Em seguida codifique a classe beCategoriaProduto.cs conforme mostra o código abaixo:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
/// <summary>
/// Summary description for beCategoriaProduto
/// </summary>
public class beCategoriaProduto
{
public beCategoriaProduto()
{
//
// TODO: Add constructor logic here
//
}
public List<CategoriaProduto> ListarTodasCategorias()
{
BloqLinqDemoDataContext bd = new BloqLinqDemoDataContext();
var query = from c in bd.CategoriaProdutos
select c;
return query.ToList();
}
}
Como você pode ver estamos fazendo uma query na tabela CategoriaProdutos e retornando TODOS os registros. O resultado da query é transformada numa lista Generics List<CategoriaProduto>.
Agora na camada de apresentação, ou UI (User Interface), faremos a chamada para os métodos da camada de negócio, ou BE (Business Layer) para o preenchimento da lista de categorias e gravação do Produto. Sendo assim, faremos:
- Preenchimento da DropDownList de Categorias de Produtos;
- Código do botão Inserir que vai preparar o objeto para ser persistido;
Segue abaixo o código para preenchimento da DropDownList de Categorias:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
beCategoriaProduto oCategProduto = new beCategoriaProduto();
ddlCategoria.DataSource = oCategProduto.ListarTodasCategorias();
ddlCategoria.DataTextField = "Descricao";
ddlCategoria.DataValueField = "CategProdID";
ddlCategoria.DataBind();
ddlCategoria.Items.Insert(0, new ListItem("Selecione ...", ""));
}
}
Em seguida, codifique o método do botão Inserir:
protected void btIncluir_Click(object sender, EventArgs e)
{
try
{
//preenche o objeto Produto
Produto oProduto = new Produto();
oProduto.Descricao = txtDescricao.Text;
oProduto.Valor = Convert.ToDecimal(txtValor.Text);
oProduto.CategProdID = Convert.ToInt32(ddlCategoria.SelectedValue);
beProduto produto = new beProduto();
produto.GravarProduto(oProduto);
lblerro.Text = "Registro incluído com sucesso";
}
catch (Exception ex)
{
lblerro.Text = ex.Message;
}
}
Execute a aplicação exemplo e debugue o código. Veja que tudo está mais claro e simples de entender. Não precisamos nos preocupar com síntaxe SQL, nem mesmo manipular os nativos objetos SqlCommand, SqlConnection, DataTable, etc.
Com certeza, o uso do LINQ tratá muita produtividade para as equipes de desenvolvimento de software.
Na próxima parte dessa série, veremos como criar querys com parâmetros, joins, group by exibindo as informações em controles ASP.NET, é claro 
Até lá !!!
Mão na massa
Continuando a série sobre LINQ to SQL , nesse post vou publicar como modelar os objetos no VS 2008 e preparar as classes para persistência dos objetos em Banco de Dados.
Crie um banco de dados no SQLEXPRESS por nome BlodDemo e duas tabelas Produtos e CategoriaProdutos. As duas tabelas se relacionam conforme figura abaixo.

Agora que já modelamos o banco, iremos modelar os objetos para que o LINQ crie as classes e faça o mapeamento com as tabelas.
No VS 2008:
- Crie um projeto do tipo WebSite e na linguagem C#
- Clique com o botão direito no projeto web, aponte para Add New Item, selecione o template LINQ to SQL Classes e dê nome de BlogLinqDemo.dbml. Veja que o VS cria o diagrama de mapeamento automaticamente.
- Aponte para o Server Explorer e adicione ou localize a conexão para o banco de dados que você criou
- Localize as duas tabelas e arraste as duas tabelas para o diagrama criado. O VS já cria as classes gerando os relacionamentos necessários. Você também pode editar os relacionamentos clicando com o botão direito no relacionamento
Veja na figura abaixo o diagrama que o VS 2008 cria no momento que você arrasta as tabelas para o diagrama.

Por trás das câmeras
É claro que não existe mágica nisso tudo. O VS é somente um modelador que gera as classes que serão executadas no seu código C#.
Se você abrir o arquivo BloqLinqDemo.designer.cs criado abaixo do BloqLinqDemo.dbml na Solution Explorer verá o código gerado para as classes. Parte do código, segue abaixo:
[Table(Name="dbo.Produtos")]
public partial class Produto : INotifyPropertyChanging, INotifyPropertyChanged
{
public Produto()
{
this._CategoriaProduto = default(EntityRef<CategoriaProduto>);
OnCreated();
}
[Column(Storage="_Descricao", DbType="NChar(10) NOT NULL", CanBeNull=false)]
public string Descricao
{
get
{
return this._Descricao
}
set
{
if ((this._Descricao != value))
{
this.OnDescricaoChanging(value);
this.SendPropertyChanging();
this._Descricao = value;
this.SendPropertyChanged("Descricao");
this.OnDescricaoChanged();
}
}
}
[Column(Storage="_Valor", DbType="Decimal(18,2) NOT NULL")]
public decimal Valor
{
get
{
return this._Valor;
}
set
{
if ((this._Valor != value))
{
this.OnValorChanging(value);
this.SendPropertyChanging();
this._Valor = value;
this.SendPropertyChanged("Valor");
this.OnValorChanged();
}
}
}
Na próxima parte dessa série, vamos criar um formulário web recebendo os valores do Cadastro de Produtos e faremos a inclusão do registro utilizando a síntaxe do LINQ
Até
Confesso que eu tive uma grande resistência ao LINQ no seu lançamento.
A minha resistência se deu exatamente em não acreditar 100% em frameworks de objeto relacional, já que os modelos que eu tinha visto até então feriam alguns conceitos de OO que para mim, na época eram importantes.
A minha frustração foi quando o LINQ chegou de vez no mercado e tomou espaço com o desenvolvimento WEB (objetos DataSource) já que a maioria das aplicações que eu desenvolvia eram WEB. A facilidade em fazer querys foi uma das coisas que me chamou a atenção no LINQ, e comecei a fazer algumas DEMOS para conhecer o produto.
Quando eu fiz a primeira DEMO, fiquei impressionado com a experiência e a produtividade de fazer um INSERT na base de dados ... percebi que o linq estava fazendo 100% do trabalho que eu vivia escrevendo manualmente, foi quando eu comecei a perceber a quantidade de tempo que eu poderia economizar, e a padronização no código que eu poderia gerar utilizando o LINQ, sem falar é claro no mapeamento Classe X Tabela que era claro e simples de entender.
Abrí a classe que o LINQ gera e ví como eu poderia customizar, melhorar, herdar, etc ... o meu medo era depender de um mapeamento sem poder criar as classes que eu quisesse e depender de criar classes somente para gravar na fonte de dados. Esse medo acabou depois dessa "olhada" mais a fundo no que foi gerado pelo LINQ.
Se você é um desenvolvedor de software, vai entender que o que fazemos hoje normalmente, repetitivamente e sempre é exatamente isso:
- Recuperar os dados da tela
- Preencher uma instancia de um objeto específico e configurar os seus valores (propriedades)
- Enviar para persistência na fonte de dados (banco, xml, txt, etc)
Esses 3 passos resumem basicamente uma operação de INSERT, UPDATE ou DELETE feito em qualquer aplicação que utilize conceito de armazenamento de dados. Não vou comentar aqui sobre os códigos que fazem acesso à banco de dados via ADO diretamente pela página ok ?
O LINQ facilita as operações basicas de consulta e persistência de objetos e gera uma grande produtividade. Além disso pode-se customizar as classes da maneira que melhor agradar. Você modela o banco de dados e gera as classes que estão prontas para gravarem as informações na sua fonte de dados.
Vou iniciar uma série básica sobre LINQ to SQL (implementação do LINQ para SQL) fazendo algumas demos usando aplicações ASP.NET e você conseguirá acompanhar passo-a-passo os principais recursos dessa tecnologia. Logo vai perceber que o LINQ gera produtividade e garante um modelo sólido de desenvolvimento.
Até a próxima !
Olá Amigos,
Estou retomando com o blog e vou postar muitas coisas legais que ando vendo sobre as novas tecnologias ASP.NET 3.5, C#, WPF, LINQ e muito mais.
Espero que seja proveitoso à todos.
abs