sexta-feira, 18 de dezembro de 2009

SELECT * FROM Tabela JOIN ListBox

Essa foi legal. Tava correndo num projeto de ASP.NET e me deparei com a seguinte situação: tenho uma ListBox que permite a seleção de várias linhas (propriedade SelectionMode = Multiple). Ela mostrava as linhas de uma tabela de domínio (lado 1 de um relacionamento 1-N). Quando o usuário selecionasse algumas linhas na listbox, eu tinha que carregar as linhas relacionadas aos valores selecionados na listbox. P.e., trabalhando no banco Northwind (um dos bancos de exemplo do SQL Server), na listbox aparecem todas as categorias; quando o usuário seleciona algumas categorias, temos que mostrar en um grid todos os produtos das categorias selecionadas:


O projeto usado é uma ASP.NET Web Application do Visual Studio 2010 Beta 2. Criei um Entity Data Model em cima do banco Northwind e importei as tabelas Products e Categories. A listbox carrega a tabela de categorias. O botão de carregar tem o seguinte código:

1    Protected Sub LinkButton1_Click(ByVal sender As Object, ByVal e As EventArgs) Handles LinkButton1.Click

2 Dim dados As New NorthwindEntities

3 Dim produtosDasCategoriasSelecionadas As New List(Of Products)

4 produtosDasCategoriasSelecionadas = _

5 (From linha As Products In dados.Products

6 Join item As Integer In (From x In ListBox1.Items Where x.Selected = True Select x.value)

7 On linha.CategoryID Equals item
8 Select linha).ToList()
9 GridView1.DataSource = produtosDasCategoriasSelecionadas

10 GridView1.DataBind()
11 End Sub

Olha só que MASSA é esse tal de Linq:
  • Linha 5: defino que a consulta vai retornar objetos da classe "Products", ou seja, produtos da tabela Products (a classe Products foi gerada pelo Entity Data Model do banco Northwind).
  • Linha 6, parte 1: Join item As Integer - faço um join entre a tabela Products e uma lista de inteiros que conterá as chaves das categorias selecionadas na listbox. Legal, né? Linq vê uma lista e faz as consultas em cima, não interessa se as listas são conjuntos de registros em uma tabela no banco, ou conjuntos de inteiros em memória.
  • Linha 6, parte 2: item As Integer In (From x In ListBox1.Items Where x.Selected = True Select x.value) Digo que a lista de inteiros (item As Integer) vai vir da listbox chamada ListBox1 (ListBox1.Items), mas só quero os inteiros para as opções selecionadas (Where x.Selected = True), e digo que estes inteiros corresponderão aos valores das opções da listbox (Select x.value). Em resumo, fiz um SELECT em cima dos itens de uma listbox, com cláusula WHERE e tudo!!!

  • Linha 7: é a condição de ligação do join, que filtra os produtos pela lista de chaves produzidas pela consulta à ListBox.

Poizé! Uma consulta Linq que traz dados de uma tabela, mas só para as linhas da tabela "relacionadas" com as opções selecionadas em uma listbox. Ou seja, um join entre uma tabela e uma listbox... :-) esse Linq é muito divertido mesmo...