Reputation: 61773
I have this function:
/// <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;
}
There are two problems with this method:
Thanks for any help! I'm using SQL Server Express 2008 R2.
Upvotes: 1
Views: 3041
Reputation: 13496
1 . Define Random class instance to have it "More random"
2 . Use the following code to select random elements
var result = Enumerable.Range(0, count).OrderBy(a => Rand.Next()).Take(resCount).Select(i => q[i]);
Upvotes: 0
Reputation: 41262
Another potential issue is that the current method does not select each record with the same probability. A simple way to see that is suppose that 9 of 10 records are desired. The current method would have only a 10% chance of selecting the first record yet it would always select the 10th record.
It seems it would be better to generate a random set of record numbers (such as described in this post). Then use those to choose those entries from the result set.
Upvotes: 0
Reputation: 15086
How random do you need the results to be?
Well you could select new anonymous random values from 'q' and afterwards order by that random number and select top count. The obvious drawback is that all articles would need to be read into memory instead of delegating the selection to db.
Upvotes: 0
Reputation: 52818
Just use the method in Random row from Linq to Sql to do an orderby ctx.Random()
and do a .Take(sampleSize)
on the results instead of FirstOrDefault
Upvotes: 5