如何在不首先将整个列表加载到内存的情况下,用Linq实现SkipWhile到Sql

本文关键字:情况下 内存 Linq Sql SkipWhile 实现 加载 列表 | 更新日期: 2023-09-27 18:23:56

我需要按发布日期降序排列存储在数据库中的文章,然后用Id == 100获取文章后面的前20条记录。

这就是我想用Linq:做的事情

IQueryable<Article> articles = 
    db.Articles
    .OrderByDescending(a => a.PublicationDate)
    .SkipWhile(a => a.Id != 100)
    .Take(20);

但是,这会生成NotSupportedException,因为在Linq-to-Sql中不支持SkipWhile(请参阅此处)。

一个可能的解决方案是执行查询,然后使用Linq将SkipWhile应用于对象:

IEnumerable<ArticleDescriptor> articles = 
    db.Articles
    .OrderByDescending(a => a.PublicationDate)
    .ToList()
    .SkipWhile(a => a.Article.Id != 100)
    .Take(20);

但这意味着我需要先将整个有序列表加载到内存中,然后在使用Id == 100的列表之后再获取20篇文章。

有没有办法避免这种巨大的内存消耗?

更一般地说,在SQL中实现这一点的最佳方法是什么?

如何在不首先将整个列表加载到内存的情况下,用Linq实现SkipWhile到Sql

根据列名,如果PublicationDate没有更改,您可以在两个单独的查询中执行此操作:

  • Id == 100建立ArticlePublicationDate
  • 检索从该日期起的20篇文章

类似于:

var thresholdDate = db.Articles.Single(a => a.Id == 100).PublicationDate;
var articles = 
    db.Articles
    .Where(a => a.PublicationDate <= thresholdDate)
    .OrderByDescending(a => a.PublicationDate)
    .Take(20);

甚至可能是LINQ到SQL可以翻译这个:

var articles = 
    db.Articles
    .Where(a => a.PublicationDate 
             <= db.Articles.Single(aa => aa.Id == 100).PublicationDate)
    .OrderByDescending(a => a.PublicationDate)
    .Take(20);

但这可能太复杂了。试试看。

你可以试试这个

var articles = 
    db.Articles
    .Where(a => a.PublicationDate < db.Articles
                                    .Where(aa => aa.Id==100)
                                    .Select(aa => aa.PublicationDate)
                                    .SingleOrDefault())
    .OrderByDescending(a => a.PublicationDate)
    .Take(20);

解决方案是否只添加where语句?

IQueryable<Article> articles = db.Articles.Where(a => a.id != 100).OrderByDescending(a => a.PublicationDate).Take(20);
相关文章: