IQueryable vs IEnumerable:IQueryable 总是更好更快吗?


  1. 如果IQueryable接口在服务器中执行查询表达式,而不是像IEnumerable那样获取所有记录,为什么IQueryable不被可以更快、更高效的IEnumerable所取代?

  2. DBSet<T>有两种口味的Where(IQueryableIEnumerable)。有没有办法调用IEnumerable版本,因为默认情况下调用IQueryable,而不调用ToList()

  1. 如果IQueryable在服务器中执行查询表达式 而不是像IEnumerable一样获取所有记录,为什么IQueryable不 取而代之的是可以更快、更高效的IEnumerable

IQueryableIEnumerable代表两种不同的东西。将IQueryable视为"问题",它本身没有任何结果。IEnumerable是一个"答案",它只有与之相关的数据,但您无法判断是什么生成了该数据。

这并不是说IQueryable每次说"更快",它只是允许您将过滤和投影放入您向 SQL 服务器提出的"问题"中,并让它只返回所需的答案(以IEnumerable的形式通过调用.ToList()或类似)。

如果您只使用IEnumerable您可以问的唯一问题是"给我您所知道的一切",然后在它给您的答案上执行过滤和投影。这就是为什么IQueryable被认为更快,因为需要处理的数据要少得多,因为您可以向服务器提出更具体的问题。

IQueryable之所以没有取代IEnumerable,是因为你问问题的东西必须能够理解你问的问题。要解析您可能要求它过滤或投影的每个可能的事情都需要做很多工作,因此大多数实现将自己限制在他们知道他们需要能够回答的常见事情上。例如,在实体框架中,当您提出问题时,它不了解如何处理,当您尝试从IQueryable获取IEnumerable(答案)时,您将收到类似于"不支持指定方法">的错误。

  1. DBSet<T>有两种Where(IQueryableIEnumerable)。 有没有办法调用IEnumerable版本,因为 默认情况下调用IQueryable,而不调用ToList()

DBSet<T>上根本没有 Where 方法。这两个Where函数来自两种扩展方法,Enumerable.WhereQueryable.Where。在调用扩展方法之前,可以通过将对象强制转换为IEnumerable<T>来强制它使用 Enumerable 重载。但是请记住,Queryable.Where过滤问题,Enumerable.Where只过滤结果。

从服务器请求结果然后将它们扔掉是浪费,所以我不建议这样做。