I have written a function that gets a given number of random records from a list. Currently I can do something like:
IEnumerable<City> cities = db.Cites.GetRandom(5);
(where db is my DataContext connecting to a SQL Server DB)
Currently, I have a function like this in every entity I need random records from:
public partial class City
{
public static IEnumerable<City> GetRandom(int count)
{
Random random = new Random();
IEnumerable<City> cities = DB.Context.Cities.OrderBy( c => random.Next() ).Take(count);
return cities;
}
}
It works fine, but I'd like it to be generic, so it can work for any table, or even any list of items. I have tried an extension method like:
public static IEnumerable<T> GetRandom<T>( this Table<T> table, int count)
{
Random random = new Random();
IEnumerable<T> records = table.OrderBy(r => random.Next()).Take(count);
return records;
}
but I get:
Error 1 The type 'T' must be a reference type in order to use it as parameter 'TEntity' in the generic type or method 'System.Data.Linq.Table'
which highlights GetRandom<T>.
I don't understand what the problem is here. Can someone clear up the proper syntax?
I like the idea of a random order function, and it can be applied to any IEnumerable like so:
public static IEnumerable<T> Randomize<T>(this IEnumerable<T> source)
{
Random rnd = new Random();
return source.OrderBy(t => rnd.Next());
}
...
IEnumerable<City> cities = db.Cites.Randomize().Take(5);
If you are talking to a database, you might want to do the random fetch at the database. With LINQ-to-SQL you can (for smallish volumes) do this via a [Function] pointing at NEWID (on the data-context):
[Function(Name="NEWID", IsComposable=true)]
public Guid Random()
{
return Guid.NewGuid();
}
then in a query via:
ctx.Log = Console.Out;
var query = from x in ctx.Suppliers
orderby ctx.Random()
select x;
var results = query.ToArray();
which gives TSQL (here using Northwind):
SELECT [t0].[SupplierID], [t0].[CompanyName], [t0].[ContactName],
[t0].[ContactTitle], [t0].[Address], [t0].[City], [t0].[Region],
[t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax], [t0].[HomePage]
FROM [dbo].[Suppliers] AS [t0]
ORDER BY NEWID()
You can obviously mix this with Take(1) etc.
It doesn't work in entity framework, though.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With