Если ваш вопрос: «Какой код я бы написал для работы в качестве фильтра в приложениях Reactive и Non-Reactive Spring, ответ будет невозможным. Вы можете написать простой класс / компонент, который будет использоваться из хотя и WebFilter или Filter.
Можно сделать это в базе данных, при помощи поддельного UDF; в частичном классе добавьте метод к контексту данных:
partial class MyDataContext {
[Function(Name="NEWID", IsComposable=true)]
public Guid Random()
{ // to prove not used by our C# code...
throw new NotImplementedException();
}
}
Тогда всего order by ctx.Random()
; это сделает случайное упорядочивание в любезности SQL Server NEWID()
. т.е.
var cust = (from row in ctx.Customers
where row.IsActive // your filter
orderby ctx.Random()
select row).FirstOrDefault();
Примечание, что это только подходит для small-to-mid-size таблиц; для огромных таблиц это окажет влияние производительности в сервере, и будет более эффективно найти количество строк (Count
), затем выбрать ту наугад (Skip/First
).
для подхода количества:
var qry = from row in ctx.Customers
where row.IsActive
select row;
int count = qry.Count(); // 1st round-trip
int index = new Random().Next(count);
Customer cust = qry.Skip(index).FirstOrDefault(); // 2nd round-trip
РЕДАКТИРОВАНИЕ: я только что заметил, что это - LINQ к SQL, не LINQ к Объектам. Используйте код Marc, чтобы заставить базу данных делать это для Вас. Я оставил этот ответ здесь как потенциальное интересное место для LINQ к Объектам.
Странно достаточно, Вы не должны на самом деле получать количество. Действительно, однако, необходимо выбрать каждый элемент, если Вы не получаете количество.
то, Что можно сделать, является содержанием идея "текущего" значения и текущего количества. Когда Вы выбираете следующее значение, берете случайное число и заменяете "ток" "новым" с вероятностью 1/n, где n является количеством.
Поэтому при чтении первого значения Вы всегда делаете это "текущим" значением. При чтении второго значения Вы могли бы делать это текущим значением (вероятность 1/2). При чтении третьего значения Вы могли бы делать это текущим значением (вероятность 1/3) и т.д., Когда у Вас закончились данные, текущее значение является случайным из всего те, Вы читаете с универсальной вероятностью.
Для применения этого с условием просто проигнорируйте что-либо, что не удовлетворяет условию. Самый легкий способ сделать, который должен только рассмотреть последовательность "соответствия" для начала, путем применения оператора Where сначала.
Вот быстрая реализация. Я думаю , это хорошо...
public static T RandomElement<T>(this IEnumerable<T> source,
Random rng)
{
T current = default(T);
int count = 0;
foreach (T element in source)
{
count++;
if (rng.Next(count) == 0)
{
current = element;
}
}
if (count == 0)
{
throw new InvalidOperationException("Sequence was empty");
}
return current;
}
Один из способов добиться эффективного - добавить столбец к вашим данным Перемешать
, заполненный случайное целое число (при создании каждой записи).
Частичный запрос для доступа к таблице в случайном порядке ...
Random random = new Random();
int seed = random.Next();
result = result.OrderBy(s => (~(s.Shuffle & seed)) & (s.Shuffle | seed)); // ^ seed);
Это выполняет операцию XOR в базе данных и упорядочивает результаты этого XOR.
Преимущества: -
Это подход, используемый моей системой домашней автоматизации для рандомизации списков воспроизведения. Он выбирает новое начальное число каждый день, обеспечивая постоянный порядок в течение дня (позволяя легко приостанавливать / возобновлять воспроизведение), но каждый новый день свежим взглядом на каждый список воспроизведения.