Wie kann ich eine Abfrage erstellen, bei der ich zufällige Zeilen abrufen würde?
Wenn ich es in SQL schreiben würde, würde ich eine Bestellung mit newid () aufgeben und n Zeilen von oben abschneiden. Wie auch immer, um dies zuerst im EF-Code zu tun?
Ich habe versucht, eine Abfrage mit newid () zu erstellen und mit DbSet.SqlQuery () auszuführen. Während es funktioniert, ist es nicht die sauberste Lösung.
Versuchen Sie außerdem, alle Zeilen abzurufen und nach einer neuen Anleitung zu sortieren. Obwohl die Anzahl der Zeilen ziemlich gering ist, ist es immer noch keine gute Lösung.
Irgendwelche Ideen?
Antworten:
Ruf einfach an:
something.OrderBy(r => Guid.NewGuid()).Take(5)
quelle
OrderBy
aus, als ob die Rangfolgefunktion stabil ist, was bei einem Zufallsgenerator nicht der Fall ist. Linq to-Entitäten übersetzen dies in eine SQL-Abfrage, die für dieselbe Entität möglicherweise ein anderes Ranking erhält (sobald Ihre Abfragen verwendet werdenInclude
). Dann wird die Entität in der Ergebnisliste dupliziert.Guid.NewGuid()
(dh LinqToSql oder was auch immer das daraus macht,NEWID()
aber niemand hat dasselbe für Oracle programmiert).Vergleich zweier Optionen:
Überspringen (zufällige Anzahl von Zeilen)
Methode
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(); }
Generiertes 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;
Guid
Methode
private T getRandomEntityInPlace<T>(IGenericRepository<T> repo) { return repo.Items.OrderBy(o => Guid.NewGuid()).First(); }
Generiertes 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
quelle
OrderBy(o => o.ID).Skip(skip).Take(5)
es nicht wirklich zufällig ist, was zu einem Engpass in der Leistung führen kann..First()
". Ich habe einen Vergleich mit einigen anderen Antworten vorgelegt, die ich gesehen habe und die nicht mehr erscheinen, sodass Ihr Punkt doppelt bestätigt wird. DieNewGuid
Lösung hat jedoch nicht das von Ihnen beschriebene Problem.