LINQ - Usando o método SelectMany


 Neste artigo vou mostrar um exemplo de utilização do operador SelectMany da LINQ usando a linguagem C#.

Vamos iniciar entendendo a diferença entre os operadores Select e SelectMany da LINQ.

O operador Select é usado para selecionar o valor de uma coleção e o operador SelectMany é usado para selecionar valores de uma coleção de coleção, ou seja, de uma coleção aninhada.



O operador Select produz um valor de resultado para cada valor de origem, enquanto SelectMany produz um único resultado que contém um valor concatenado para cada valor de origem.

Na verdade, o operador SelectMany transforma  um  IEnumerable<IEnumerable<T>> em IEnumerable<T>, ou seja, uma  lista de lista para uma lista.

Como exemplo vamos usar um arquivo XML chamado Livros.xml localizado na pasta c:\dados :

<?xml version="1.0" encoding="utf-8" ?>
<Livros>
  <Livro >
    <Titulo>ASP.NET MVC</Titulo>
    <ISBN>aspmvc</ISBN>
    <Lancamento>11/11/2013</Lancamento>
    <Paginas>200</Paginas>
    <Editor>1</Editor>
    <Autor>
      <Nome>Jose</Nome>
      <Sobrenome>Macoratti</Sobrenome>
    </Autor>
  </Livro>
  <Livro>
    <Titulo>C#.NET</Titulo>
    <ISBN>c#2</ISBN>
    <Lancamento>10/11/2015</Lancamento>
    <Paginas>500</Paginas>
    <Editor>1</Editor>
    <Autor>
      <Nome>David</Nome>
      <Sobrenome>Anderson</Sobrenome>
    </Autor>
  </Livro>
  <Livro>
    <Titulo>VB.NET</Titulo>
    <ISBN>vb3</ISBN>
    <Lancamento>5/5/2012</Lancamento>
    <Paginas>400</Paginas>
    <Editor>1</Editor>
    <Autor>
      <Nome>Robert</Nome>
      <Sobrenome>Johnantan</Sobrenome>
    </Autor>
  </Livro>
  <Livro>
    <Titulo>ASP .NET Core</Titulo>
    <ISBN>aspncore</ISBN>
    <Lancamento>6/9/2018</Lancamento>
    <Paginas>300</Paginas>
    <Editor>2</Editor>
    <Autor>
      <Nome>Jose</Nome>
      <Sobrenome>Macoratti</Sobrenome>
    </Autor>
  </Livro>
  <Livro>
    <Titulo>JAVA</Titulo>
    <ISBN>java5</ISBN>
    <Lancamento>8/5/2014</Lancamento>
    <Paginas>400</Paginas>
    <Editor>3</Editor>
    <Autor>
      <Nome>David</Nome>
      <Sobrenome>Anderson</Sobrenome>
    </Autor>
  </Livro>
  <Livro>
    <Titulo>HTML</Titulo>
    <ISBN>html6</ISBN>
    <Lancamento>9/5/2013</Lancamento>
    <Paginas>400</Paginas>
    <Autor>
      <Nome>Roger</Nome>
      <Sobrenome>Zimmerman</Sobrenome>
    </Autor>
  </Livro>
</Livros>

Nota: Os dados são fictícios e usados apenas a título de exemplo.

Vamos consultar o elemento autor cujo sub elemento é nome e sobrenome e vamos obter apenas os autores cujo nome for Jose ou David.

Recursos Usados:

Criando o projeto Windows Forms

Abra o VS 2017 Community e crie um projeto usando o template Windows Classic Desktop -> Windows Forms App com o nome LINQ_SelectMany;

No formulário padrão inclua os controles :

Definindo o código do formulário

No evento Click do botão - btnCarregarXML - temos o código que vai apenas exibir o XML no TextBox - txtDados:

       private void btnCarregarXML_Click(object sender, EventArgs e)
        {
            try
            {
                XElement dadosXML = XElement.Load(@"c:\dados\XML\Livros.xml");
                txtDados.Text = dadosXML.ToString();
                btnSelectMany.Enabled = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Erro ao carregar XML : " + ex.Message);
            }
        }

Neste código estamos apenas carregando arquivo Livros.xml que esta na pasta c:\dado\XML  exibindo-o no TextBox - txtDados.

No evento Click do botão - btnSelecMany - temos o código que vai usar o SelectMany e chamar o método GetLivros() para extrair os elementos Titulo e Nome para os autores Jose e David :

        private void btnSelectMany_Click(object sender, EventArgs e)
        {
            string[] strAutores = { "Jose", "David" };

            var livros = strAutores.SelectMany(n => GetLivros(n));

            foreach (var objLivro in livros)
            {
                txtXML.Text = "Livro : " + objLivro.Element("Titulo").Value + " Nome Autor : "
 + objLivro.Element("Autor").Element("Nome").Value + "\r\n";
            }
        }

Abaixo temos o código do método GetLivros() que recebe o nome do autor e realiza uma consulta LINQ para obter os dados do arquivo XML:

        public IEnumerable<XElement> GetLivros(string autor)
        {
            XDocument objDoc = XDocument.Load(@"c:\dados\XML\Livros.xml");

            var objQuery = objDoc.Descendants("Livro")
                                      .Where(b => b.Elements("Autor")
                                            .Elements("Nome")
                                             .Any(aut => (string)aut == autor));

            return objQuery;
        }

Agora é só alegria...

Executando o projeto teremos o seguinte resultado:

Este é um exemplo prático de utilização do operador LINQ SelectMany.

Pegue o projeto aqui : LINQ_SelectMany.zip  (sem as referências)

"Sabendo que, se o nosso coração nos condena, maior é Deus do que o nosso coração, e conhece todas as coisas."
1 João 3:20

Referências:


José Carlos Macoratti