2012-09-14 14 views
16

estoy aprendiendo acerca de LINQ a SQL y todo iba bien hasta que algo extraño sucedió:DISTINCT() y orderBy tema

Traté de hacer un ejemplo de distinct, por lo que, mediante el dabatase Neptuno escribí el siguiente consulta:

var query = 
    from o in db.Orders 
    orderby o.CustomerID 
    select new 
    { 
     o.CustomerID 
    }; 

Si imprimo el SQL generado por LINQ a SQL para la consulta almacenada en query se ve así:

SELECT [t0].[CustomerID] 
FROM [dbo].[Orders] AS [t0] 
ORDER BY [t0].[CustomerID] 

Por lo tanto, como de costumbre, la consulta trae todos los CustomerID para cada Order en la tabla Orders ordenada alfabéticamente.

¡Pero! Si utilizo el método Distinct() así:

var query = (
    from o in db.Orders 
    orderby o.CustomerID 
    select new 
    { 
     o.CustomerID 
    }).Distinct(); 

La consulta trae los resultados esperados de la cláusula Distinct, pero los CustomerID s no están clasificadas pesar de que escribí orderby o.CustomerID!

La consulta SQL para esta segunda consulta LINQ es la siguiente:

SELECT DISTINCT [t0].[CustomerID] 
FROM [dbo].[Orders] AS [t0] 

Como podemos ver en la cláusula ** ORDER BY no se encuentra. ¿Porqué es eso?

¿Por qué la cláusula ORDER BY desaparece cuando utilizo el método Distinct()?

+1

Como acotación al margen de sintaxis lambda es mucho más simple para las consultas de este tipo: 'var query = db.Orders.Select (o => o .CustomerId) .Distinct(); ' – asawyer

Respuesta

28

Desde el Queryable.Distinct documentation;

El comportamiento esperado es que devuelve una secuencia desordenada de los elementos únicos en el origen.

En otras palabras, cualquier orden del IQueryable existente ha se pierde cuando se utiliza Distinct() en él.

Lo que desea es probablemente algo más como esto, un OrderBy() después de Distinct() está hecho;

var query = (from o in db.Orders 
      select new 
      { 
       o.CustomerID 
      }).Distinct().OrderBy(x => x.CustomerID); 
8

Intente reorganizar los miembros para colocar el OrderBy después de Distinct. Vas a tener que volver a método de encadenamiento:

db.Orders.Select(o=>o.CustomerId).Distinct().OrderBy(id=>id); 

Esta sería la forma más eficiente para establecer la consulta en LINQ Enumerable de todos modos, debido a que el OrdenarPor entonces funcionar solamente en los artículos únicos y no en todos ellos. Además, de acuerdo con MSDN, Enumerable.Distinct no garantiza el orden de devolución de los elementos de todos modos, por lo que ordenar antes de la deduplicación no tiene sentido.

+3

No, es por diseño. – asawyer

+0

... Sí lo es: http://msdn.microsoft.com/en-us/library/system.linq.enumerable.distinct.aspx. La pregunta es, ¿por qué Distinct no mantiene el orden de los elementos de entrada, cuando tan fácilmente podría hacerlo simplemente devolviendo el rendimiento? – KeithS

+2

@KeithS ¿Has leído tu enlace ... "La secuencia de resultados no está ordenada". No es un error cuando está integrado en el diseño. –

3

Debido al uso de distinto, el orden de la lista devuelta no está garantizado. LinqToSql es lo suficientemente inteligente como para reconocer esto, por lo que lo ignora.

Si realiza el pedido DESPUÉS de su Distinto, todo sucederá como lo desee.

var query = (from o in db.Orders 
      select new 
      { 
       o.CustomerID 
      }).Distinct().OrderBy(o => o.CustomerID); 

o

var query = db.Orders.Select(o => o.CustomerID).Distinct().OrderBy(o => o.CustomerID); 

Consulta este artículo para aclarar:

http://programminglinq.com/blogs/marcorusso/archive/2008/07/20/use-of-distinct-and-orderby-in-linq.aspx

1

Puede simular orderBy y distinta con este counstruction:

var distinctItems = employees.GroupBy(x => x.EmpID).OrderBy(x => x).Select(y => y.First());