Andrey Sanches

é MVP em ASP/ASP.NET e escreve sobre desenvolvimento WEB com tecnologias Microsoft

Série LINQ to SQL Parte 5 - Criando querys com JOIN entre tabelas

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á

 

Posted: Thu, Sep 24 2009 7:39 by andrey | with 6 comment(s)
Filed under: ,

Comments

Leandro said:

Olá, tudo bem? Estou tentando fazer um select com o left join e não estou conseguindo fazer a iteração, como faço para isso? Ocorre o seguinte erro:

LINQ to Entities does not recognize the method '<>f__AnonymousType9`5[System.Int32,System.String,System.String,System.Int32,System.String] ElementAtOrDefault[<>f__AnonymousType9`5](System.Linq.IQueryable`1[<>f__AnonymousType9`5[System.Int32,System.String,System.String,System.Int32,System.String]], Int32)' method, and this method cannot be translated into a store expression.

Obrigado desde já,

Leandro

# October 19, 2009 10:03 AM

andrey said:

Olá Leandro, como vai ?

Poderia por favor postar seu código ?

abs

# October 19, 2009 11:17 AM

Emiliano Eloi Silva Barbosa said:

 E ai Andrey, beleza?

Minha questão está em como colocar essa pesquisa em uma Classe de negócio. Qual o tipo de retorno que devo utilizar uma vez que não consigo usar o List<Produto>, pois ele retorna uma Entidade 'Nova' ou mesclada. Observe Meu código:

   public List<Produto> RecuperarTodosProdutos()

   {

       var query = from regProduto in dconBlogDemo.Produtos

                   join regCategoriaProduto in dconBlogDemo.CategoriaProdutos

                   on regProduto.CategProdID equals regCategoriaProduto.CategProdID

                   select new { ID = regProduto.ProdutoID,

                                Descricao = regProduto.Descricao,

                                Categoria = regCategoriaProduto.Descricao};

       return query.ToList();

   }

Muito obrigado!

# October 29, 2009 3:57 PM

andrey said:

Olá Emiliano,

Não entendi o problema em colocar esse método em uma classe de negócio. Não há problema algum em retornar uma lista de Produtos List<Produto>. Você está recebendo alguma mensagem de erro nessa sua query ? Ao invés de usar o "select new" tente usar somente "select regProduto;"

abs

# October 29, 2009 4:12 PM

Emiliano Eloi Silva Barbosa said:

  Buenas!

  Se eu utilizar o regProduto eu retorno um Objeto Produto, dessa forma não vou ter a Descrição da categoria do produto. Na verdade o que eu quero fazer é colocar a query linq que você fez nesse post dentro de uma classe de negócio e setar o dataSource do gridView da seguinte forma:

beProduto produto = new beProduto();

GridView1.DataSource = produto.RecuperaTodosProdutos();

Valew!

# October 30, 2009 7:30 AM

andrey said:

Olá Emiliano,

Então o que você quer fazer é exatamente o que eu fiz no post. Qual o problema que você está tendo em retornar a lista de produtos exibindo a categoria de cada produto?

Como você mesmo fez, deu nome à cada campo de retorno e é exatamente esse nome que você vai usar de bind nas colunas da GridView.

O seu código está correto, ainda não entendi qual dificuldade você está tendo em colocar esse método numa classe de negócios.

abs

# October 30, 2009 7:47 AM
Leave a Comment

(required) 

(required) 

(optional)

(required)