Как реализовать SkipWhile с Linq to Sql без предварительной загрузки всего списка в память?
мне нужно заказать статей, хранящихся в базе данных по убыванию даты публикации, а затем взять первые 20 записей после статьи Id == 100
.
это то, что я хотел бы сделать с LINQ:
IQueryable<Article> articles =
db.Articles
.OrderByDescending(a => a.PublicationDate)
.SkipWhile(a => a.Id != 100)
.Take(20);
однако это создает исключение NotSupportedException, потому что SkipWhile
не поддерживается в Linq to Sql (см. здесь).
возможным решением является выполнение запроса, а затем применение SkipWhile
использование Linq для Объект:
IEnumerable<ArticleDescriptor> articles =
db.Articles
.OrderByDescending(a => a.PublicationDate)
.ToList()
.SkipWhile(a => a.Article.Id != 100)
.Take(20);
но это означает, мне нужно, чтобы загрузить весь список в памяти, а затем взять 20 статей после Id == 100
.
есть ли способ избежать этого огромного потребления памяти?
В общем, каков наилучший способ достичь этого в SQL?
3 ответов
если, как я предполагаю из названия столбца,PublicationDate
не изменяется, вы можете сделать это в двух отдельных запросах:
- установить
PublicationDate
наArticle
СId == 100
- получить 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 to 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);