Tri*_*ick 2 c# linq generics extension-methods
我编写了一个函数,从列表中获取给定数量的随机记录.目前我可以这样做:
IEnumerable<City> cities = db.Cites.GetRandom(5);
Run Code Online (Sandbox Code Playgroud)
(其中db是我的DataContext连接到SQL Server数据库)
目前,我在每个需要随机记录的实体中都有这样的函数:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
它工作正常,但我希望它是通用的,所以它可以适用于任何表,甚至任何项目列表.我尝试了一种扩展方法,如:
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;
}
Run Code Online (Sandbox Code Playgroud)
但我得到:
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'
哪些亮点GetRandom<T>.
我不明白这里的问题是什么.有人可以清理正确的语法吗?
我喜欢随机顺序函数的想法,它可以应用于任何IEnumerable,如下所示:
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);
Run Code Online (Sandbox Code Playgroud)
如果您正在与数据库通信,则可能需要在数据库中执行随机提取.使用LINQ-to-SQL,您可以(对于较小的卷)通过指向NEWID的[Function](在数据上下文中)执行此操作:
[Function(Name="NEWID", IsComposable=true)]
public Guid Random()
{
return Guid.NewGuid();
}
Run Code Online (Sandbox Code Playgroud)
然后在查询中通过:
ctx.Log = Console.Out;
var query = from x in ctx.Suppliers
orderby ctx.Random()
select x;
var results = query.ToArray();
Run Code Online (Sandbox Code Playgroud)
这给了TSQL(这里使用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()
Run Code Online (Sandbox Code Playgroud)
你可以将它与Take(1)等混合使用.
但是,它在实体框架中不起作用.