关于c#:IQueryable和IEnumerable之间差异的真实例子?

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查询并在服务器端运行。dataeData的唯一区别是,在第二种情况下,您可以立即处理查询结果(即枚举并放入列表)。如果要使用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查询,所有的书都应该从服务器下载到客户机。


以下代码行不会在内存中提取记录,除非您使用ToList()对其进行迭代或具体化:

1
var data = context.Books.Where(x => x.Id > 930); // this does not immediately executes query

在这种情况下,当您放入ToList()时,只有查询将在服务器上执行,结果将被带到内存中,这是第一个和最后一个代码示例的主要区别。

唯一要记住的是使它成为IEnumerable,将导致执行查询,并且所有结果都将加载到内存中。


IEnumerable最适合内存中的收集,这意味着数据已经在您的列表中,您可以对此进行查询。

iqueryable最适合使用OData查询的API调用。它将准备SQL或命令。当我们尝试使用查询结果时,只有它会点击数据库来获取数据。