Невозможно преобразовать IQueryable ‹› в ошибку IOrderedQueryable

У меня есть следующий код LINQ:

    var posts = (from p in db.Posts
         .Include("Site")
         .Include("PostStatus")
        where p.Public == false
        orderby p.PublicationTime 
        select p);

        if (!chkShowIgnored.Checked) {
            posts = posts.Where(p => p.PostStatus.Id != 90);
        }

Эта последняя строка (дополнительное место) выдает ошибку:

Невозможно неявно преобразовать тип System.Linq.IQueryable в System.Linq.IOrderedQueryable.

Я не уверен, что это означает ...
Почему я получаю эту ошибку?
Она появилась после того, как я добавил в запрос предложение "orderby", до этого он скомпилировался нормально, так что у меня есть своего рода догадка о том, что происходит, но я не могу понять это.


person Daniel Magliola    schedule 13.11.2009    source источник


Ответы (2)


Попробуйте объявить posts конкретно как IQueryable<Post>, а не var (который заберет IOrderedQueryable<Post> (он все равно будет заказан).

В качестве альтернативы, измените структуру так, чтобы мы заказывали в конце, что позволяет (при желании) добавить where посередине:

var posts = from p in db.Posts
             .Include("Site")
             .Include("PostStatus")
            where p.Public == false
            select p);

if (!chkShowIgnored.Checked) {
    posts = posts.Where(p => p.PostStatus.Id != 90);
}
var finalQuery = posts.OrderBy(p => p.PublicationTime);

(очевидно, смотрим на finalQuery)

Причина ошибки в том, что в настоящее время у вас есть (по сути):

IOrderedQueryable<Post> posts = {snip};
...
posts = {something (Where) that returns IQueryable<Post>}
person Marc Gravell    schedule 13.11.2009
comment
Оба работали как шарм, спасибо! Что вы имеете в виду, мы заказываем в конце, а не в середине? Разве фактический SQL не генерируется и не выполняется после всего этого, после того, как запрос будет перечислен? Я предположил, что LINQ будет достаточно умен, чтобы объединить WHERE ... - person Daniel Magliola; 14.11.2009
comment
Это OrderBy, который изменяет подпись ... делая OrderBy последним, что мы применяем, у нас есть IQueryable<T> повсюду, что легче составить. Как вы говорите, провайдер (EF, LINQ-to-SQL и т. Д.) Все равно объединит все перед выполнением. - person Marc Gravell; 14.11.2009
comment
Ааааа, это последнее объяснение СУПЕР ясное, понятно. Спасибо!! - person Daniel Magliola; 14.11.2009

Результат лямбда-выражения имеет тип IQueryable. Он не позволяет использовать метод расширения Where, поэтому для его использования сначала необходимо преобразовать его, например, в список.

Вы можете сделать это, используя

posts = posts.ToList().Where(p => p.PostStatus.Id != 90);
person eKek0    schedule 13.11.2009
comment
Хммммм, но разве сначала не будет выполнен запрос, который принесет все записи из базы данных, а затем отфильтрует их по статусу в ASP.Net? Я бы предпочел, чтобы БД обрабатывала все WHERE, что, как я думал, произошло, если бы я просто добавил предложение .Where, поскольку SQL будет сгенерирован и выполнен позже, когда результаты будут перечислены. В вашем случае ToList () тоже не вызывает его выполнение? - person Daniel Magliola; 14.11.2009