¿Cómo puedo crear una consulta en la que recuperaría filas aleatorias?
Si tuviera que escribirlo en SQL, pondría un pedido en newid () y cortaría n número de filas desde la parte superior. De todos modos, ¿hacer esto en el código EF primero?
Intenté crear una consulta que usa newid () y ejecutarla usando DbSet.SqlQuery (). mientras funciona, no es la solución más limpia.
Además, intente recuperar todas las filas y ordenarlas por una nueva guía. Aunque el número de filas es bastante pequeño, todavía no es una buena solución.
¿Algunas ideas?
Respuestas:
Solo llama:
something.OrderBy(r => Guid.NewGuid()).Take(5)
fuente
OrderBy
asume que la función de clasificación es estable, lo que no es el caso con un generador aleatorio. Linq a entidades traduce esto a una consulta sql que puede obtener una clasificación diferente para la misma entidad (tan pronto como se utilicen sus consultasInclude
). Luego, hace que la entidad se duplique en la lista de resultados.Guid.NewGuid()
(es decir, LinqToSql o lo que sea que lo convierta,NEWID()
pero nadie programó lo mismo para Oracle).Comparando dos opciones:
Saltar (número aleatorio de filas)
Método
private T getRandomEntity<T>(IGenericRepository<T> repo) where T : EntityWithPk<Guid> { var skip = (int)(rand.NextDouble() * repo.Items.Count()); return repo.Items.OrderBy(o => o.ID).Skip(skip).Take(1).First(); }
SQL generado
SELECT [GroupBy1].[A1] AS [C1] FROM (SELECT COUNT(1) AS [A1] FROM [dbo].[People] AS [Extent1]) AS [GroupBy1]; SELECT TOP (1) [Extent1].[ID] AS [ID], [Extent1].[Name] AS [Name], [Extent1].[Age] AS [Age], [Extent1].[FavoriteColor] AS [FavoriteColor] FROM (SELECT [Extent1].[ID] AS [ID], [Extent1].[Name] AS [Name], [Extent1].[Age] AS [Age], [Extent1].[FavoriteColor] AS [FavoriteColor], row_number() OVER (ORDER BY [Extent1].[ID] ASC) AS [row_number] FROM [dbo].[People] AS [Extent1]) AS [Extent1] WHERE [Extent1].[row_number] > 15 ORDER BY [Extent1].[ID] ASC;
Guid
Método
private T getRandomEntityInPlace<T>(IGenericRepository<T> repo) { return repo.Items.OrderBy(o => Guid.NewGuid()).First(); }
SQL generado
SELECT TOP (1) [Project1].[ID] AS [ID], [Project1].[Name] AS [Name], [Project1].[Age] AS [Age], [Project1].[FavoriteColor] AS [FavoriteColor] FROM (SELECT NEWID() AS [C1], [Extent1].[ID] AS [ID], [Extent1].[Name] AS [Name], [Extent1].[Age] AS [Age], [Extent1].[FavoriteColor] AS [FavoriteColor] FROM [dbo].[People] AS [Extent1]) AS [Project1] ORDER BY [Project1].[C1] ASC
fuente
OrderBy(o => o.ID).Skip(skip).Take(5)
no será realmente aleatorio, lo que podría convertirse en un cuello de botella en el rendimiento..First()
". Estaba presentando una comparación entre algunas otras respuestas que había visto y que ya no aparecen, por lo que su punto está doblemente validado. Pero laNewGuid
solución no tendrá el problema que describe.