问题 无法将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”子句,之前它编译得很好,所以我对所发生的事情有一种预感,但我无法完全理解它。


2739
2017-11-13 22:12


起源



答案:


尝试声明 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>}

19
2017-11-13 22:21



两者都像魅力一样,谢谢!你是什​​么意思我们在最后而不是在中间订购?一旦查询被枚举,是不是在所有这些之后生成并执行了实际的SQL?我认为LINQ足够智能“结合”WHERE ...... - Daniel Magliola
OrderBy通过使OrderBy成为我们应用的最后一件事来改变签名...... IQueryable<T> 贯穿始终,更容易撰写。正如您所说,提供程序(EF,LINQ-to-SQL等)将在执行之前合并所有内容。 - Marc Gravell♦
Aaaaah,最后的解释是超级明确,陷入困境。谢谢!! - Daniel Magliola


答案:


尝试声明 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>}

19
2017-11-13 22:21



两者都像魅力一样,谢谢!你是什​​么意思我们在最后而不是在中间订购?一旦查询被枚举,是不是在所有这些之后生成并执行了实际的SQL?我认为LINQ足够智能“结合”WHERE ...... - Daniel Magliola
OrderBy通过使OrderBy成为我们应用的最后一件事来改变签名...... IQueryable<T> 贯穿始终,更容易撰写。正如您所说,提供程序(EF,LINQ-to-SQL等)将在执行之前合并所有内容。 - Marc Gravell♦
Aaaaah,最后的解释是超级明确,陷入困境。谢谢!! - Daniel Magliola


lambda表达式的结果是IQueryable类型。它不允许扩展方法Where,所以首先使用它必须将它转换为例如列表。

你可以这样做

posts = posts.ToList().Where(p => p.PostStatus.Id != 90);

-5
2017-11-13 22:16



嗯,但不会首先执行一个查询,它将从数据库中提取所有记录,然后按ASP.Net中的状态过滤它们?我宁愿让DB处理所有的WHERE,如果我刚刚添加了.Where子句,这就是我认为发生的事情,因为SQL会在枚举结果时生成并执行。在你的情况下,ToList()是否也导致它也被执行? - Daniel Magliola