Как я могу создать запрос, в котором я получу случайные строки?
Если бы я написал это на SQL, я бы поставил заказ на newid () и отрубил бы n строк сверху. В любом случае, сначала сделать это в коде EF?
Я попытался создать запрос, использующий newid (), и выполнить его с помощью DbSet.SqlQuery (). пока он работает, это не самое чистое решение.
Кроме того, попытался получить все строки и отсортировать их по новому идентификатору. Хотя количество строк довольно мало, это все же не лучшее решение.
Есть идеи?
Ответы:
Просто позвони:
something.OrderBy(r => Guid.NewGuid()).Take(5)
источник
OrderBy
предполагается, что функция ранжирования стабильна, чего нельзя сказать о случайном генераторе. Linq to entity преобразует это в sql-запрос, который может получить разный рейтинг для одного и того же объекта (как только ваши запросы будут использоватьInclude
). Затем это приводит к дублированию объекта в списке результатов.Guid.NewGuid()
(имеется в виду LinqToSql или что-то еще,NEWID()
но никто не программировал то же самое для Oracle).Сравнение двух вариантов:
Пропустить (случайное количество строк)
Метод
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
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;
Гид
Метод
private T getRandomEntityInPlace<T>(IGenericRepository<T> repo) { return repo.Items.OrderBy(o => Guid.NewGuid()).First(); }
Сгенерированный SQL
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
источник
OrderBy(o => o.ID).Skip(skip).Take(5)
он не будет действительно случайным, что может стать узким местом в производительности..First()
". Я представлял сравнение между некоторыми другими ответами, которые я видел, которые больше не появляются, так что ваша точка зрения дважды подтверждается. Но вNewGuid
решении не будет проблемы, которую вы описываете.