2012-03-19 10 views
13

La siguiente declaración básica de LINQ to SQL no da como resultado que el orden funcione. Como puede ver en el T-SQL, no hay ningún orden por. ¿Sabes por qué?¿LINQ to SQL no genera ORDER BY cuando se usa DISTINCT?

LINQ a SQL:

 var results = (from stats in db.t_harvest_statistics 
         orderby stats.unit_number 
         select stats.unit_number).Distinct().ToList(); 

datos arriba indicados siguientes TSQL

SELECT 
[Distinct1].[unit_number] AS [unit_number] 
FROM (SELECT DISTINCT 
[Extent1].[unit_number] AS [unit_number] 
FROM [dbo].[t_harvest_statistics] AS [Extent1] 
    ) AS [Distinct1] 
+0

Es número_unidad una columna de identidad? – asawyer

+0

no, unit_number no es identidad. Es un tipo de datos int. – KeelRisk

Respuesta

28

Eso es una limitación de SQL y Álgebra Relacional de donde el ORDER BY es en relación al DISTINTO.

El ORDER BY debe estar "más alejado" en el SQL (en el "nivel superior") ya que es una operación de vista . Mientras que uno puede escribir SQL que tiene el PEDIDO POR "más adentro", en relación con una operación RA, a menudo resulta en Comportamiento Indefinido (que a veces funciona). En este sentido, tiene sentido que Linq2Sql sea libre de ignorar ORDEN POR, aunque, tal vez una excepción sería mejor ... sería menos sutil de todos modos ;-) (En realidad, este mismo problema existe para cualquier proveedor de Linq eso no proporciona una definición "más estricta" de Distinct.)

Elimine el Distinct() y el Linq2Sql debe generar nuevamente el ORDER BY como se esperaba. La solución es simplemente cambiar el orden de las operaciones para que ORDER BY vuelva a estar en el "nivel superior".

Esto está cubierto por el artículo Use of Distinct and OrderBy in LINQ:

Este comportamiento puede parecer extraño. El problema es que el operador Distinct no garantiza que mantendrá el orden de valores original. Aplicado a LINQ to SQL, esto significa que una restricción de clasificación puede ser ignorada en el caso de una consulta como queryA.

La solución es bastante s [i] MPLE: poner el operador OrdenarPor después de que el uno distinto, como en la siguiente definición queryB:

var queryB = 
    (from o in db.Orders 
    select o.Employee.LastName) 
    .Distinct().OrderBy(n => n); 

de codificación feliz.

+1

. Estoy un poco confundido por el (n => n) ... ¡pero funciona! – KeelRisk

+1

@KeelRisk 'OrderBy' necesita algo ya que no hay sobrecarga' OrderBy() '(que, si existiera, se definiría de la misma manera). Supongo que el caso de 'OrderByYeSelf' no se determinó para ser lo suficientemente especial ;-) –

0

Tengo el mismo problema al ordenar el año de la tabla de transacciones.

probar esto

var results = (from stats in db.t_harvest_statistics 
         select stats.unit_number).Distinct().OrderBy(x =(Int16)x.unit_number).ToList(); 

después de obtener el valor diferenciado utilice OrdenarPor método