-
如果
IQueryable
接口在服务器中执行查询表达式,而不是像IEnumerable
那样获取所有记录,为什么IQueryable
不被可以更快、更高效的IEnumerable
所取代? -
DBSet<T>
有两种口味的Where
(IQueryable
和IEnumerable
)。有没有办法调用IEnumerable
版本,因为默认情况下调用IQueryable
,而不调用ToList()
?
- 如果
IQueryable
在服务器中执行查询表达式 而不是像IEnumerable
一样获取所有记录,为什么IQueryable
不 取而代之的是可以更快、更高效的IEnumerable
?
IQueryable
和IEnumerable
代表两种不同的东西。将IQueryable
视为"问题",它本身没有任何结果。IEnumerable
是一个"答案",它只有与之相关的数据,但您无法判断是什么生成了该数据。
这并不是说IQueryable
每次说"更快",它只是允许您将过滤和投影放入您向 SQL 服务器提出的"问题"中,并让它只返回所需的答案(以IEnumerable
的形式通过调用.ToList()
或类似)。
如果您只使用IEnumerable
您可以问的唯一问题是"给我您所知道的一切",然后在它给您的答案上执行过滤和投影。这就是为什么IQueryable
被认为更快,因为需要处理的数据要少得多,因为您可以向服务器提出更具体的问题。
IQueryable
之所以没有取代IEnumerable
,是因为你问问题的东西必须能够理解你问的问题。要解析您可能要求它过滤或投影的每个可能的事情都需要做很多工作,因此大多数实现将自己限制在他们知道他们需要能够回答的常见事情上。例如,在实体框架中,当您提出问题时,它不了解如何处理,当您尝试从IQueryable
获取IEnumerable
(答案)时,您将收到类似于"不支持指定方法">的错误。
DBSet<T>
有两种Where
(IQueryable
和IEnumerable
)。 有没有办法调用IEnumerable
版本,因为 默认情况下调用IQueryable
,而不调用ToList()
?
类DBSet<T>
上根本没有 Where 方法。这两个Where
函数来自两种扩展方法,Enumerable.Where
和Queryable.Where
。在调用扩展方法之前,可以通过将对象强制转换为IEnumerable<T>
来强制它使用 Enumerable 重载。但是请记住,Queryable.Where
过滤问题,Enumerable.Where
只过滤结果。
从服务器请求结果然后将它们扔掉是浪费,所以我不建议这样做。