2010-07-26 13 views
12

Estoy usando Asp.net MVC con Sharp Architecture.Pedido de Linq ThreadSafe al azar para usar en ASP.NET

tengo este código:

return _repositoryKeyWord.FindAll(x => x.Category.Id == idCAtegory) 
       .Take(50).ToList(); 

Como puedo ordenar por azar? Nota: no quiero pedir los 50 elementos extraídos, quiero un pedido antes y luego extraer 50 elementos.

thks

+0

¿Estás diciendo que quieres la lista completa aleatorizada y luego quieres recuperar los primeros 50 elementos? –

+0

Esta pregunta no duplica la pregunta vinculada. Esta pregunta específicamente denota ASP.NET que requiere acceso aleatorio ThreadSafe. La pregunta vinculada no menciona a ThreadSafe –

Respuesta

32

Una manera de lograr de manera eficiente es agregar una columna a sus datos Shuffle que se completa con un int aleatorio (a medida que se crea cada registro).

la consulta para acceder a la tabla a continuación, se convierte en ...

Random random = new Random(); 
int seed = random.Next(); 
result = result.OrderBy(s => (~(s.Shuffle & seed)) & (s.Shuffle | seed)); //^seed); 

Esto hace una operación XOR en la base de datos y órdenes por los resultados de esa XOR.

Ventajas: -

  1. eficiente: SQL se encarga de la ordenación , no hay necesidad de buscar a toda la tabla
  2. repetible: (bueno para pruebas) - puede usar la misma semilla aleatoria para generar el mismo al azar fin
  3. funciona en la mayoría (todos?) Entity Framework admite bases de datos

Este es el enfoque utilizado por mi sistema domótico para aleatorizar listas de reproducción. Escoge una nueva semilla cada día, dando un orden constante durante el día (lo que permite una fácil pausa/reanudación de las funciones), pero una nueva mirada a cada lista de reproducción cada nuevo día.

+5

Esta solución me hizo ir ooooo y ahhhh. – jfar

+1

jfar: Yo también; es grandioso. Aunque acabo de utilizar el PK (que es un int) en lugar de un campo Shuffle y funciona muy bien. Gracias Hightechrider! –

+1

¡Esto es simplemente increíble! Usé PK también. El rendimiento es sobresaliente –

1
Random random = new Random(); 
return _repositoryKeyWord.FindAll(x => x.Category.Id == idCAtegory) 
       .OrderBy(x => r.Next()) 
       .Take(50).ToList(); 
+0

Ja, me gusta eso. Sin embargo, si está utilizando una ordenación rápida, podría fallar. Sé que intentar usar Array.Sort en un parámetro incoherente causará una excepción. –

+0

Me gustaría ver el sql que genera. ¿Devuelve toda la mesa, luego ordena y tira todo excepto los 50 principales registros? –

+0

Ah, sí, eso debería ser. Tome (50) .OrderBy (x => r.Next()), no al revés. Editar: no importa, leí mal la pregunta. –

1

Probablemente lo mejor para escribir su propio método de extensión para hacerlo.

public static class Extensions 
{ 
    static readonly Random random = new Random(); 

    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> items) 
    { 
     return Shuffle(items, random); 
    } 

    public static IEnumerable<T> Shuffle<T>(this IEnumerable<T> items, Random random) 
    { 
     // Un-optimized algorithm taken from 
     // http://en.wikipedia.org/wiki/Knuth_shuffle#The_modern_algorithm 
     List<T> list = new List<T>(items); 
     for (int i = list.Count - 1; i >= 1; i--) 
     { 
      int j = random.Next(0, i); 
      T temp = list[i]; 
      list[i] = list[j]; 
      list[j] = temp; 
     } 
     return list; 
    } 
} 
+0

Aleatorio.Siguiente no es seguro para subprocesos, por lo que no puede usar la variable estática para almacenar el valor aleatorio compartido aquí. –

+0

Y sin duda, debe haber i--, no i ++ –

+0

-1 por no ser seguro en cuanto a los hilos y puede fallar en ASP.NET –

2

Usted puede hacer esto en T-SQL como se describe here. No creo que puedas hacerlo en Linux sin cargar todo el conjunto de resultados en la memoria y luego tirar la mayor parte, lo cual no quieres hacer.

-2

¿Qué tal esto?

return _repositoryKeyWord.FindAll(x => x.Category.Id == idCAtegory) 
    .OrderBy (x => Guid.NewGuid()) 
    .Take(50).ToList(); 
+1

Esto no funciona. – nfplee

+0

Esto no funcionaría porque Guid.NewGuid() se traducirá a SQL y fallará. –