OBS: Para este artigo, estou levando em consideração o seguinte cenário:

Ordenar uma query por vários campos é algo comum e que todos nós, se já não precisamos, um dia precisaremos. Fazer isso com o LINQ é relativamente simples e pode ser algo desse tipo:

// C#
var produtos = from p in context.PRODUTOS
               orderby p.VL_PRECO, p.NM_PRODUTO
               select p;
foreach (var p in produtos)
{
    Console.WriteLine("{0}: {1}",
                      p.NM_PRODUTO,
                      ((decimal)p.VL_PRECO).ToString("N2"));
}
' VB.NET
Dim produtos = From p In context.PRODUTOS _
               Order By p.VL_PRECO, p.NM_PRODUTO _
               Select p
For Each p As PRODUTOS In produtos
    Console.WriteLine("{0}: {1}",
                      p.NM_PRODUTO,
                      CDec(p.VL_PRECO).ToString("N2"))
Next

No exemplo acima, é possível ver que basta enfileirar os campos que desejar ordenar, separados por vírgula, no Order By.

Como seria essa mesma ordenação usando Lambda Expression? A Lambda Expression nos oferece o extension method OrderBy(). Muita gente imagina que usando essa extensão seguidas vezes, ou seja, OrderBy().OrderBy(), resolverá o problema de ordenar por vários campos. Isso não acontece, pois as opções de ordem informadas no segundo OrderBy() substituem as opções do primeiro.

Ou então, usar o operador “&&” ou “And” entre as condições de ordenação. Isso também não funciona.

// C#
// forma errada: o segundo OrderBy substitui o primeiro
var produtos = context.PRODUTOS
                      .OrderBy(p => p.VL_PRECO)
                      .OrderBy(p => p.NM_PRODUTO);

// forma errada: colocar && entre as opções de ordenação não resolve
// essa forma gera erros em tempo de compilação e não executa a aplicação
var produtos = context.PRODUTOS
                      .OrderBy(p => p.VL_PRECO &&
                                    p.NM_PRODUTO);
' VB.NET
' forma errada: o segundo OrderBy substitui o primeiro
Dim produtos = context.PRODUTOS _
                      .OrderBy(Function(p) p.VL_PRECO) _
                      .OrderBy(Function(p) p.NM_PRODUTO)

' forma errada: colocar And entre as opções de ordenação não resolve
' essa forma gera erros em tempo de compilação e não executa a aplicação
Dim produtos = context.PRODUTOS _
                      .OrderBy(Function(p) p.VL_PRECO And _
                               Function(p) p.NM_PRODUTO)

O importante neste caso é saber o que a Lambda Expression com OrderBy() retornará um objeto do tipo IQueriable. A interface IQueriable implementa a interface IEnumerable que é normalmente utilizada ao criar um ObjectQuery. Já o OrderBy(), retorna um objeto IOrderedEnummerable que, por sua vez, disponibiliza novos extension methods, entre eles, ThenBy() e ThenByDescending().Isto significa que podemos ordenar com vários campos pela utilização de OrderBy() e ThenBy() juntos.

Veja no exemplo abaixo como seria a ordenação correta:

// C#
// forma correta: OrderBy().ThenBy()
var produtos = context.PRODUTOS
                      .OrderBy(p => p.VL_PRECO)
                      .ThenBy(p => p.NM_PRODUTO);

foreach (var p in produtos)
{
    Console.WriteLine("{0}: {1}",
        p.NM_PRODUTO,
        ((decimal)p.VL_PRECO).ToString("N2"));
}
' VB.NET
' forma correta: OrderBy().ThenBy()
Dim produtos = context.PRODUTOS _
                      .OrderBy(Function(p) p.VL_PRECO) _
                      .ThenBy(Function(p) p.NM_PRODUTO)

For Each p As PRODUTOS In produtos
    Console.WriteLine("{0}: {1}",
                      p.NM_PRODUTO,
                      CDec(p.VL_PRECO).ToString("N2"))
Next

É interessante ressaltar que essas mesmas regras valem para OrderByDescending() e ThenByDescending().

Código fonte

Este código fonte pode ser baixado aqui.

Anúncios