【问题标题】:When to expect IEnumerable and when to expect IQueryable from a Linq query何时期望 IEnumerable 以及何时期望来自 Linq 查询的 IQueryable
【发布时间】:2011-09-28 14:32:11
【问题描述】:

我无法理解 Linq 何时给我一个 IQueryable 结果,什么时候给我一个 IEnumerable 结果。

示例:
我正在使用 EF,我有两个实体 LocationConfiguration。 每个Location可以有多个Configurations

以下查询给了我一个 IQueryable 作为结果:

Context.Locations.Where(l => l.Name == "SomeName")

而以下结果是给我一个 IEnumerable:

Context.Locations.Where(l => l.Name == "SomeName").First().Configurations.Select(c => c)

这是为什么呢?

【问题讨论】:

  • 第一个查询是给你IQueryable?你积极吗?那应该实现一个对象,不应该有IQueryableIEnumerable
  • @AnthonyPegram 你是对的。我从示例中删除了 .First() 以进行澄清。

标签: c# linq entity-framework


【解决方案1】:

一般来说,IQueryable(在Queryable 中定义)上的 LINQ 扩展方法返回 IQueryables,而 IEnumerable(在Enumerable 中定义)上的扩展方法返回 IEnumerables。在这种特殊情况下,Configurations 是第一个返回的 Location 对象的集合 (IEnumerable)。因此,.Select 调用返回一个 IEnumerable。

编辑:要使其全部远程执行,您可以试试这个:

Context.Locations.Where(l => l.Name == "SomeName").Configurations

假设您对 Locations 的过滤器只返回一行,您应该得到相同的结果。当然它会是一个 IQueryable,但这不应该有所作为。如果您需要实现它,您可以执行以下操作:

Context.Locations.Where(l => l.Name == "SomeName").Configurations.ToList()

【讨论】:

  • 这有点道理,因为 Configurations 是 EF 中的一个集合。但在数据库中它仍然是一个单独的表。如何确保整个查询将在 SQL Server 中而不是在内存中执行?
  • 尝试将 First 调用移到堆栈的下方。我将编辑我的答案。
  • 我会接受这个答案,因为您回答了我的问题。关于您在服务器上执行它的建议,它不起作用。来自Context.Locations.Where(..) 的结果不包含配置的定义,因为它的类型是IQueriable<Location>。我现在有点担心我的其他一些查询,这些查询比这要大得多。我想我将不得不使用 SQL Profiler 来验证服务器上实际执行的内容。
  • 对于那些好奇的人:我的查询,Context.Locations.Where(l => l.Name == "SomeName").First().Configurations.Select(c => c)实际上是在 SQL Server 上分两步执行的。首先获取位置,然后使用sp_executesql 获取配置。通过重写 Linq 查询,我可以一次性在 SQL Server 中执行所有操作,这正是我想要的。
【解决方案2】:

基本上,IQueryable 允许远程数据源(如 SQL Server)。如果可能,它将对数据库起作用。 IEnumerable 适用于内存中的集合。

因此,如果您正在查询 SQL Server 数据库,您将获得一个 IQueryable。否则它将是一个 IEnumerable。

这个article 可以进一步帮助你。

【讨论】:

    猜你喜欢
    • 2016-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-28
    • 2020-06-09
    • 1970-01-01
    • 1970-01-01
    • 2020-12-21
    相关资源
    最近更新 更多