2012-02-26 31 views
45

¿Cómo puedo cambiar el código a continuación, para obtener cada vez 50 datos aleatorios diferentes de la base de datos?linq: ordenar por orden aleatorio

return (from examQ in idb.Exam_Question_Int_Tbl 
     where examQ.Exam_Tbl_ID==exam_id 
     select examQ).OrderBy(x=>x.Exam_Tbl_ID).Take(50); 

Respuesta

87

http://msdn.microsoft.com/en-us/library/system.guid.newguid.aspx

return (from examQ in idb.Exam_Question_Int_Tbl 
     where examQ.Exam_Tbl_ID==exam_id 
     select examQ).OrderBy(x => Guid.NewGuid()).Take(50); 

Si esto es LINQ a SQL que podría simplemente añadir un ORDER BY NEWID() a la instrucción SELECT.

como se ha comentado que podría ser mejor usar un algoritmo como Fisher-Yates Shuffle, aquí es una implementación: https://stackoverflow.com/a/375446/284240

+0

No creo que esto funcione de todos modos con una base de datos (sin traducción a SQL) y termina siendo O (nlogn) en el mejor de los casos. En cualquier caso, su comparador necesita proporcionar un total de pedidos (no es así). Puede solucionarlo seleccionando un nuevo GUID (una vez) para cada elemento, luego ordenando por eso, pero Fisher-Yates Shuffle (versión de Durstenfeldt) es una mejor opción si está haciendo una selección aleatoria en la memoria. – tvanfosson

+8

-1 http://blogs.msdn.com/b/ericlippert/archive/2011/01/20/spot-the-defect-bad-comparisons-part-one.aspx. en el tiempo t: A> B es verdadero debido a su 'x => Guid.NewGuid()'. en el tiempo t + n: A Guid.NewGuid()'. Las funciones de ordenación no están diseñadas para mezclar elementos y podría dar lugar a un ciclo infinito en el peor de los casos. –

+0

Para ampliar mi sugerencia, '.Seleccione (x => nuevo {Guid = Guid.NewGuid, Question = x}) .OrderBy (x => x.Guid). Seleccione (x => x.Question) .Take (50); 'funcionaría para una selección en memoria PERO usted tiene que ordenarla, que es en promedio O (nlogn) para los mejores algoritmos. El algoritmo de Durstenfeldt funciona tomando una colección e intercambiando cada elemento con un elemento aleatorio en la colección que aún no ha iterado. Esto proporciona un orden aleatorio pero solo requiere operaciones O (n). – tvanfosson

9

¿Qué tan grande es la colección? ¿Puedes seleccionarlos todos en la memoria y luego elegir una colección aleatoria? Si es así, entonces el algoritmo Shuffle en Is using Random and OrderBy a good shuffle algorithm? sería una buena opción.

return idb.Exam_Question_Int_Tbl 
      .Where(e => e.Exam_Tbl_ID == exam_id) 
      .ToList() 
      .Shuffle() 
      .Take(50); 

Si no es así, entonces yo sugeriría un procedimiento almacenado que hace un pedido por newid() (SQL Server Random Sort). No creo que haya ninguna forma de traducir una expresión basada en un generador de números aleatorios en C# a LINQ a SQL/Entities.

+1

¿Qué ocurre con la Combinación de Saltar y Tomar? – gdoron

3

Si usted tiene el mismo problema, que tenía ...

int Limit = 24; 
return (from Q in Context.table 
where Q.some_key == 1234 
select new classDataType() { 
    FirstAttribute = Q.FirstCol, 
    SecondAttribute = Q.SecondCol, 
    ThirdAttribute = Q.ThirdCol 
}).ToList().OrderBy(x => Guid.NewGuid()).Take(Limit).ToList(); 

después de SQL-LINQ tiene que ser una lista, así que tal vez U necesidad de cambiar a una lista, antes de que esté utilizando el OrderBy-NewGuid-Method:

return (...-SQL-SELECT-LINQ-...) 
    .ToList() //**** 
    .OrderBy(x => Guid.NewGuid()).Take(Limit).ToList();