Подтвердить что ты не робот

Как реализовать 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 к Object:

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

Но это означает, что мне нужно сначала загрузить весь упорядоченный список в память, а затем взять 20 статей после Id == 100.

Есть ли способ избежать этого огромного потребления памяти?

В общем, что лучший способ добиться этого в SQL?

4b9b3361

Ответ 1

Если, как я предполагаю, из имени столбца 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);

но это может быть слишком сложным для него. Попробуйте и посмотрите.

Ответ 2

Вы можете попробовать как это

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);

Ответ 3

Не стоит ли просто добавлять оператор where?

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