2010-03-29 8 views
6

¿Hay alguna forma de refactorizar este código? La única diferencia es el orden por parte.La consulta de LINQ necesita ascender o descender en la misma consulta

Idealmente me gustaría usar una expresión delegado/lambda lo que el código es reutilizable, pero no sé cómo agregar y quitar condicionalmente la OrdenarPor operadores de consulta y OrderByDescending

var linq = new NorthwindDataContext(); 

     var query1 = linq.Customers 
      .Where(c => c.ContactName.StartsWith("a")) 
      .SelectMany(cus=>cus.Orders) 
      .OrderBy(ord => ord.OrderDate) 
      .Select(ord => ord.CustomerID); 

     var query2 = linq.Customers 
      .Where(c => c.ContactName.StartsWith("a")) 
      .SelectMany(cus => cus.Orders) 
      .OrderByDescending(ord => ord.OrderDate) 
      .Select(ord => ord.CustomerID); 

Respuesta

12

Usted puede crear su propio método de extensión reutilizable que hará esto:

public static IOrderedQueryable<TSource> OrderBy<TSource, TKey> 
    (this IQueryable<TSource> source, 
    Expression<Func<TSource, TKey>> keySelector, 
    bool ascending) 
{ 
    return ascending ? source.OrderBy(keySelector) 
      : source.OrderByDescending(keySelector); 
} 

y lo mismo para ThenBy:

public static IOrderedQueryable<TSource> ThenBy<TSource, TKey> 
    (this IOrderedQueryable<TSource> source, 
    Expression<Func<TSource, TKey>> keySelector, 
    bool ascending) 
{ 
    return ascending ? source.ThenBy(keySelector) 
      : source.ThenByDescending(keySelector); 
} 
+0

Genial. Gracias Jon. –

+0

Un poco fuera de tema, pero lo anterior se traducirá correctamente a Linq2SQL? IOW ¿es lo suficientemente inteligente como para ver un método "no compatible" y ejecutarlo antes de construir un árbol de sintaxis y generar el SQL? Solo me pregunto, nunca lo intenté. :) – leppie

+1

@leppie: Es solo llamar a los métodos Queryable existentes: esos son los que crean el árbol de expresiones. Tenga en cuenta que esto * no * funcionará contra 'IEnumerable ' en este momento, aunque podría escribir fácilmente métodos de extensión equivalentes que lo harían. –

0

Con números, etc. normalmente puede negar la 'variable de pedido'.

Con DateTime, no estoy tan seguro. Podría intentar usar un Timespan.

2

Puede dividir su consulta en bits y usar la lógica de control de flujo. ¡LINQ to SQL construirá mágicamente la consulta correcta como si lo hubiera escrito todo en una línea! La razón por la que esto funciona es porque la consulta no se envía a la base de datos hasta que usted solicita los datos, sino que se almacena como una expresión.

var linq = new NorthwindDataContext(); 
var query = linq.Customers 
    .Where(c => c.ContactName.StartsWith("a")) 
    .SelectMany(cus=>cus.Orders); 

IOrderedQueryable<Order> query2; 
if (useAscending) { 
    query2 = query.OrderBy(ord => ord.OrderDate); 
} else { 
    query2 = query.OrderByDescending(ord => ord.OrderDate); 
} 

var query3 = query2.Select(ord => ord.CustomerID); 
+0

Errorrr !!!!!!!!! Su orden debe suceder antes de seleccionar, de lo contrario se trata de un tipo diferente :) – leppie

+0

Gracias Mark. ¿Importa si el orden de los operadores de consulta se coloca después de la selección()? –

+0

@leppie: Sí, lo siento, ¡no me di cuenta de eso! –

0

Bueno, si usted tiene una condición donde se decide si la orden por es ascendente o descendente puede utilizar esta

var query1 = linq.Customers 
.Where(c => c.ContactName.StartsWith("a")) 
.SelectMany(cus=>cus.Orders) 

if(SortAscending) 
    query1 = query1.OrderBy(ord => ord.OrderDate); 
else 
    query1 = query1.OrderByDescending(ord => ord.OrderDate); 

var query2 = query1.Select(ord => ord.CustomerID); 
+0

Mira, cometiste el mismo error que la respuesta siguiente (ahora está corregido). – leppie

+0

@leppie: No solo es fijo, sino que está arriba ahora, no debajo. ¡Entonces su comentario es impreciso y probablemente más confuso que útil! ¿Por qué no simplemente repites tu comentario en lugar de intentar usar una referencia? En otras palabras, simplemente escriba esto: 'Su orden debe suceder antes de seleccionar, de lo contrario, se trata de un tipo diferente'. ;-) –

+0

Allí lo arregló. Sin embargo, creo que prefiero la respuesta de Jon también ;-) –

1
return from T in bk.anbarsabts 
     where T.kalaname == str 
     orderby T.date descending 
     select new { T.date, T.kalaname, T.model, T.tedad };