Real example of the differences between IQueryable and IEnumerable?
我知道IQueryable的优点是在服务器上运行过滤器,而不是将所有记录加载到像IEnumerable这样的内存中,但是在代码中,这到底是怎样的,例如,如果我有这个代码:
1
| var data = context.Books.Where(x => x.Id > 930); |
如果我有1000条记录,那么它将只加载70条记录,为了对它们进行迭代,我将data转换为list:
1
| var list = data.ToList(); //has only 70 records |
但是,如果必须先通过IQueryable,那么IEnumerable加载所有记录的情况是什么?即获得上述示例的IEnumerable版本:
1
| var eData = context.Books.Where(x => x.Id > 930).ToList(); |
它们是一样的吗?最后一个代码不超过两行代码的组合?
代码中没有IEnumerable示例。两个
1
| var data = context.Books.Where(x => x.Id >930); // Queryable.Where(Expression) |
和
1
| var eData = context.Books.Where(x => x.Id >930).ToList(); // Queryable.Where(Expression) |
使用IQueryable扩展将表达式转换为SQL查询并在服务器端运行。data和eData的唯一区别是,在第二种情况下,您可以立即处理查询结果(即枚举并放入列表)。如果要使用IEnumerable:
1
| var eData = context.Books.AsEnumerable().Where(x => x.Id >930); // Enumerable.Where(Lambda) |
这里的区别在于,您可以使用过滤器谓词中的任何代码来过滤集合。因为这个谓词不会转换成要在服务器端运行的SQL。例如,您可以运行自定义方法:
1
| var eData = context.Books.AsEnumerable().Where(x => _someObject.CheckBook(x)); |
但是为了运行IEnumerable查询,所有的书都应该从服务器下载到客户机。
- 这与将变量定义为IQueryable或IEnumerable:IEnumerable list = context.Books.Where(x => x.Id >930);IQueryable data = context.Books.Where(x => x.Id >930);相同吗?
- @Mohamedahmed如果您使用IEnumerable list = context.Books.Where(x => x.Id >930);,那么您将存储IQueryable,它对IEnumerable变量有一些查询。这意味着-所有进一步的行动都将使用IEnumerable扩展。如list.Where(x => x.Title !="")将在客户方执行。但第一部分将在数据库端执行
- 所以这里的假设是错误的:haroldrv.com/2015/02/…(见最后一个例子)
- @穆罕默德是的,这个例子是错误的。当应用LINQ扩展时,传递给该扩展的对象很重要。db.Clients为IQueryable。因此,Take(5)将应用于可查询。SQL查询将在ToList()调用上执行,只有此调用的结果才会被clients变量引用。这篇文章也有其他错误
- 最后一个问题:你的方式是唯一的方式吗(最常见的方式?)是否获取获取与IQueryable相反的所有记录的IEnumerable列表?(我不可能认为所有围绕IEnumerable接口的麻烦都是关于我以前从未使用过或见过其他方法的!)
- @Mohamedahmed你是在说AsEnumerable()扩展吗?
- 在Sergey Berezovskiy,是的
- @Mohamedahmed这不是唯一的方法,但最常见的方法是,因为您可以继续查询构造,而无需声明单独的IEnumerabl变量或将可查询的结果放入一些内存中的集合(如list)。
- 非常感谢,你的答案非常有用
以下代码行不会在内存中提取记录,除非您使用ToList()对其进行迭代或具体化:
1
| var data = context.Books.Where(x => x.Id > 930); // this does not immediately executes query |
在这种情况下,当您放入ToList()时,只有查询将在服务器上执行,结果将被带到内存中,这是第一个和最后一个代码示例的主要区别。
唯一要记住的是使它成为IEnumerable,将导致执行查询,并且所有结果都将加载到内存中。
IEnumerable最适合内存中的收集,这意味着数据已经在您的列表中,您可以对此进行查询。
iqueryable最适合使用OData查询的API调用。它将准备SQL或命令。当我们尝试使用查询结果时,只有它会点击数据库来获取数据。