Jul*_*lin 110 .net c# linq-to-sql
当我有条件时,使用Linq to SQL检索随机行的最佳(和最快)方法是什么,例如某些字段必须为true?
Mar*_*ell 167
您可以使用假UDF在数据库中执行此操作; 在部分类中,向数据上下文添加方法:
partial class MyDataContext {
[Function(Name="NEWID", IsComposable=true)]
public Guid Random()
{ // to prove not used by our C# code...
throw new NotImplementedException();
}
}
Run Code Online (Sandbox Code Playgroud)
然后就是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();
Run Code Online (Sandbox Code Playgroud)
请注意,这仅适用于中小型表; 对于大型表,它会对服务器产生性能影响,找到行数(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
Run Code Online (Sandbox Code Playgroud)
Kon*_*kus 59
实体框架的另一个示例:
var customers = db.Customers
.Where(c => c.IsActive)
.OrderBy(c => Guid.NewGuid())
.FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)
这不适用于LINQ to SQL.在OrderBy简单地被丢弃.
Jon*_*eet 31
编辑:我只是注意到这是LINQ to SQL,而不是LINQ to Objects.使用Marc的代码让数据库为您完成此操作.我在这里留下这个答案作为LINQ to Objects的潜在兴趣点.
奇怪的是,你实际上并不需要计算.但是,除非得到计数,否则你需要获取每个元素.
你能做的就是保持"当前"值和当前计数的概念.当你获取下一个值时,取一个随机数并用"new"替换"current",概率为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;
}
Run Code Online (Sandbox Code Playgroud)
Ian*_*cer 19
实现高效实现的一种方法是在数据Shuffle中添加一个用随机int填充的列(当创建每个记录时).
以随机顺序访问表的部分查询是......
Random random = new Random();
int seed = random.Next();
result = result.OrderBy(s => (~(s.Shuffle & seed)) & (s.Shuffle | seed)); // ^ seed);
Run Code Online (Sandbox Code Playgroud)
这在数据库中执行XOR操作,并按XOR的结果进行排序.
好处:-
这是我的家庭自动化系统用于随机化播放列表的方法.它每天都会选择一个新的种子,在白天提供一致的顺序(允许轻松的暂停/恢复功能),但每个新的一天都要重新审视每个播放列表.
如果你想var count = 16从表中获得例如随机行,你可以写
var rows = Table.OrderBy(t => Guid.NewGuid())
.Take(count);
Run Code Online (Sandbox Code Playgroud)
这里我使用EF,表是Dbset