从DB返回随机对象(LINQ查询)

时间:2012-01-06 08:42:12

标签: c# linq

我有以下查询:

Banner banner = Database.Banners.Where(b => b.IsPublish.Value && 
         b.Category.Value == (int) CategoryBanner.Banner &&
         b.PeriodShowCountAlready < b.PeriodShowCount ||
         b.ShowNext < DateTime.Now ).Take(1).FirstOrDefault();

我只检索一条记录。假设在DB 3记录中满足此查询并且LINQ将始终返回相同的记录。我想要返回的随机记录,我该怎么做?

3 个答案:

答案 0 :(得分:3)

根据您的数据库,这可能有效:

var banners = Database.Banners.Where(b => b.IsPublish.Value && 
         b.Category.Value == (int) CategoryBanner.Banner &&
         b.PeriodShowCountAlready < b.PeriodShowCount ||
         b.ShowNext < DateTime.Now );

然后只是跳过随机数量的横幅......

var skip = new Random().Next(banners.Count() - 1);
var banner = banners.Skip(skip).FirstOrDefault();

正如Amar指出的那样,这种方法不是最优的,因为它会导致两次数据库之旅。根据我自己的经验分析,往返另一台服务器往往比执行一个简单的SQL语句花费更多。

那么,有什么选择?

  • 获取整个集合,并在本地选择随机横幅。这不是最佳的,因为该集合可能非常大。如果您知道该集合较小(少于1000条没有二进制字段的记录[如横幅图像],或者少于10k,则总的来说应该可以忽略不计)

  • 首先询问数据库有多少个对象,然后向数据库询问第n个对象。这很糟糕,因为它导致两次旅行。

  • 让数据库完成所有操作,让您的ORM保持舒适,并手动编写存储过程 。为此,你可以按参数顺序使用newid()[在sql server上],一切都快速而且好,但你必须在服务器上而不是在你的C#应用​​程序中这样做。

答案 1 :(得分:2)

<强>更新 重复问题中的(更好)answer提供了Skip的示例。这样做的好处是空列表处理。此外,这个答案讨论了大型结果集的问题,这些问题在我的解决方案中无法很好地处理......

您可以从数据库中返回多个,并从结果中选择一个随机条目。

List<Banner> list = Database.Banners.Where(b => b.IsPublish.Value && 
         b.Category.Value == (int) CategoryBanner.Banner &&
         b.PeriodShowCountAlready < b.PeriodShowCount ||
         b.ShowNext < DateTime.Now ).Take(10).ToList();

Random r = new Random();
Banner banner = list.Count == 0 ? null : list[r.Next(0, list.Count)];

答案 2 :(得分:0)

获取所有记录并对其进行随机

尝试这样做:

 var records = Database.Banners.Where(b => b.IsPublish.Value && 
 b.Category.Value == (int) CategoryBanner.Banner &&
 b.PeriodShowCountAlready < b.PeriodShowCount ||
 b.ShowNext < DateTime.Now ).ToList();
 var random = new Random();
 var count = random.Next(records.Count - 1);
 Banner banner = records[count];