使用扩展方法查询IEnumerable是否等同于使用IQueryable ?

本文关键字:等同于 是否 IQueryable 查询 扩展 方法 IEnumerable | 更新日期: 2023-09-27 18:13:13

我理解IQueryable和IEnumerable之间的主要区别。IQueryable在数据库中执行查询并返回过滤后的结果,而IEnumerable将完整的结果集放入内存并在内存中执行过滤查询。

我不认为使用扩展方法来查询变量的初始赋值会导致它像IQueryable一样在数据库中执行,但我只是想确保。

这段代码将导致从数据库返回person的完整结果集,然后在内存中进行过滤:

(上下文的People属性是DbSet类型)

IEnumerable<Person> people = context.People;
Person person = people.Where(x => x.FirstName == "John");

即使我在将项目分配给变量之前将下面的过滤添加为扩展方法,我假设这段代码应该以与上面的代码相同的方式工作,并在过滤之前将完整的结果集带回内存,对吗?

Person person = context.People.Where(x => x.FirstName == "John");
编辑:

谢谢你们的回复。我修改了代码示例以显示我的意思(删除了代码第二段中的IEnumerable)。

同时,为了澄清上下文。People的类型是DbSet,它同时实现了IQueryable和IEnumerable。所以我不确定哪个。where方法被调用了。智能感知告诉我这是可查询的版本,但这可以信任吗?当直接使用上下文的DbSet时,情况总是这样吗?

使用扩展方法查询IEnumerable是否等同于使用IQueryable ?

IEnumerable<Person> people = context.People;
Person person = people.Where(x => x.FirstName == "John");

…将执行IEnumerable。其中方法扩展,它接受一个Func<TSource, bool> predicate参数,强制在内存中进行过滤。

相反…

IEnumerable<Person> people = context.People.Where(x => x.FirstName == "John");

…将执行IQueryable其中方法扩展,它接受一个Expression<Func<TSource, bool>> predicate参数。请注意,这是一个表达式,而不是一个委托,它允许它将where条件转换为数据库条件。

所以你调用的扩展方法是有区别的

IQueryable练习表情。它实际上是一个查询生成器,在不做任何事情的情况下积累有关查询的信息……直到您需要从中获取一个值,当:

  • 以目标语言(例如SQL)从累积的表达式生成查询
  • 查询被执行,通常在数据库上,
  • 结果被转换回c#对象。

IEnumerable扩展适用于预编译函数。当您需要从中获取值时:

    这些函数中的c#代码被执行。

这两者很容易混淆,因为:

  • 都有相似名字的扩展函数,
  • lambda语法对于表达式和函数是相同的-所以你不能区分它们,
  • 使用"var"来声明变量删除了数据类型(通常是使用哪个接口的唯一线索)。

    IQueryable<int> a;
    IEnumerable<int> b;
    int x1 = a.FirstOrDefault(i => i > 10);    // Expression passed in
    int x2 = b.FirstOrDefault(i => i > 10);    // Function passed in
    

具有相同名称的扩展方法通常做相同的事情(因为它们是这样写的),但有时它们不是。

所以答案是:不,它们不相等