IQueryable 和 IEnumerable 之间区别的真实示例?

Real example of the differences between IQueryable and IEnumerable?

我知道 IQueryable 在服务器上具有 运行 过滤器的优势,而不是像 IEnumerable 那样将所有记录加载到内存中,但是这在代码中看起来如何,例如,如果我有这个代码:

var data = context.Books.Where(x => x.Id > 930);

如果我有 1000 条记录,那么它只会加载 70 条记录,为了遍历它们,我将 data 转换为列表:

var list = data.ToList(); //has only 70 records

但是如果必须先通过IQueryableIEnumerable加载所有记录的情况是什么? 即获取上述示例的 IEnumerable 版本:

var eData = context.Books.Where(x => x.Id > 930).ToList();

它们不一样吗?最后的代码无非就是把上面两行代码结合起来?

您的代码中没有 IEnumerable 示例。两者

var data = context.Books.Where(x => x.Id >930); // Queryable.Where(Expression)

var eData = context.Books.Where(x => x.Id >930).ToList(); // Queryable.Where(Expression)

使用 IQueryable 扩展将表达式转换为 SQL 查询并在服务器端 运行 转换。 dataeData 之间的唯一区别是您在第二种情况下立即处理查询结果(即枚举它们并放入列表)。如果你想使用 IEnumerable:

var eData = context.Books.AsEnumerable().Where(x => x.Id >930); // Enumerable.Where(Lambda)

这里的不同之处在于,您可以在过滤谓词中使用任何代码来过滤集合。因为这个谓词在服务器端不会被转换成SQL到运行。例如。您可以 运行 您的自定义方法:

var eData = context.Books.AsEnumerable().Where(x => _someObject.CheckBook(x));

但是所有的书都要从服务器下载到客户端才能运行 IEnumerable查询。

以下代码行不会获取内存中的记录,直到您迭代它或使用 ToList() 实现它:

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

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

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

IEnumerable 最适合 In-Memory 集合,这意味着数据已经在您的列表中,您可以在上面查询。

IQueryable 最适合 Api 使用 OData 的调用 queries.It 将准备 Sql 或 command.when 我们尝试使用查询结果,然后只有它会访问数据库获取数据。