Метод Linq для возврата случайного набора записей - PullRequest
1 голос
/ 23 июня 2011

У меня есть эта функция:

/// <summary>
/// Returns an array of random articles, ID and titles only
/// </summary>
/// <param name="SectionID">Section ID to return</param>
/// <param name="Count">Number of articles to return</param>
/// <returns></returns>
public ArticleOverview[] RandomArticles(int SectionID, int Count)
{
    ArticleOverview[] ReturnLinks;

    // Pick a random tutorial and redirect to it
    using (MainContext db = new MainContext())
    {
        // Select rows
        var q = (from c in db.tblArticles where c.IsDeleted == false && c.SectionID == SectionID select new { c.ID, c.Title });
        int count = q.Count();
        int index = new Random().Next(count);
        var Articles = q.Skip(index).Take(Count);

        // Size array
        ReturnLinks = new ArticleOverview[Articles.Count()];

        int InsertIx = 0;
        foreach (var Rec in Articles)
        {
            ReturnLinks[InsertIx] = new ArticleOverview(Rec.ID, Rec.Title, SectionID);
            InsertIx++;
        }
    }

    return ReturnLinks;
}

У этого метода есть две проблемы:

  • Если он выберет одну из последних записей, он вернет меньше записей больше, чем предполагалось, т.е. если число наборов записей равно 100, и мы выбираем 10 записей, и он возвращает индекс 95, он вернет только 5 записей, а не 10
  • Возвращенные записи упорядочены, они не перемешаны.Возвращенные записи должны быть рандомизированы и не упорядочены, поскольку они последовательно существуют в базе данных.

Спасибо за любую помощь!Я использую SQL Server Express 2008 R2.

Ответы [ 4 ]

4 голосов
/ 23 июня 2011

Просто используйте метод в Случайная строка от Linq до Sql , чтобы сделать orderby ctx.Random() и сделать .Take(sampleSize) для результатов вместо FirstOrDefault

0 голосов
/ 23 июня 2011

1. Определите случайный экземпляр класса, чтобы он был «Более случайный»

2. Используйте следующий код для выбора случайных элементов

var result = Enumerable.Range(0, count).OrderBy(a => Rand.Next()).Take(resCount).Select(i => q[i]);
0 голосов
/ 23 июня 2011

Другая потенциальная проблема заключается в том, что текущий метод не выбирает каждую запись с одинаковой вероятностью. Простой способ убедиться в этом - предположить, что желательно 9 из 10 записей. Текущий метод будет иметь только 10% шанс выбрать первую запись, но он всегда будет выбирать 10-ую запись.

Кажется, было бы лучше создать случайный набор номеров записей (например, , описанный в этом посте ). Затем используйте их, чтобы выбрать эти записи из набора результатов.

0 голосов
/ 23 июня 2011

Насколько случайными должны быть результаты?

Ну, вы можете выбрать новые анонимные случайные значения из 'q' и затем упорядочить по этому случайному числу и выбрать верхний счет.Очевидный недостаток заключается в том, что все статьи нужно будет читать в память, а не делегировать выборку в db.

...