我有以下查询:
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将始终返回相同的记录。我想要返回的随机记录,我该怎么做?
答案 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];