此处的任何人都可以明确告诉我有关IEnumerable
和IQueryable
以及某些示例帮助的不同之处?
谢谢
答案 0 :(得分:4)
IEnumerable<>
界面表示可以枚举某些内容 - 换句话说,您可以对其进行foreach
循环。
IQueryable<>
接口表示某些内容具有某种支持查询提供程序,它能够查看提供给它的表达式,并将它们转换为某种查询。
这些很容易让人感到困惑,部分原因是IQueryable<>
扩展了IEnumerable<>
,并且有一种名为.AsQueryable()
的扩展方法可以导致任何IEnumerable<>
(例如List<>
转换为IQueryable<>
。
有多种扩展方法称为&#34; LINQ方法&#34;在Enumerable
命名空间中的Queryable
和System.Linq
类中。它们看起来几乎完全相同,并且它们的语法几乎相同,这进一步增加了您的困惑,但存在一些关键差异。 Enumerable
类上的对象可以处理IEnumerable<>
个对象,并且具有Func<>
个签名。 Queryable
课程中的IQueryable<>
课程对Expression<Func<>>
个对象有效,签名为Expression<Func<>>
。
令人困惑的是,C#语言会自动推断您是否尝试根据上下文创建Func<>
或var e = new[]{1,2,3,4,5}.AsEnumerable();
var q = e.AsQueryable();
var eStrings = e.Select(i => i.ToString());
var qStrings = q.Select(i => i.ToString());
,因此使用情况完全相同在许多情况下也一样。例如:
Func<int, string> eSelect = i => i.ToString();
var eStrings = e.Select(eSelect);
Expression<Func<int, string>> qSelect = i => i.ToString();
var qStrings = q.Select(qSelect);
最后两行看起来是一样的,但他们实际上做的事情却截然不同。编译器正在为您有效地生成以下代码:
.ToList()
如果你对这些结果做了Func<>
,那么第一个就会调用给定的Func<int, string> func = qSelect.Compile();
var s = func(1); // returns "1"
,它实际上是一个函数(你可以传递一个方法名而不是lambda表达式,例如),对于列表中的每个项目。第二个首先必须首先将表达式编译成函数,然后调用该编译的表达式。
IQueryable<>
这显然是更多的工作。那我们为什么要.ToList()
?因为在某些情况下,知道某人想要做什么比实际运行他们给你的代码更重要。例如,如果您使用的是LINQ to Entities或LINQ to SQL等提供程序,那么运行var personIdStrings = Persons.Select(p => p.PersonId.ToString()).ToList();
会导致此提供程序查看完整查询,其表达式保持不变,并认识到您想要的是数字并将它们变成字符串。所以像这样的查询:
SELECT CONVERT(NVarChar,[t0].[PersonId]) AS [value]
FROM [Person] AS [t0]
...实际上会导致生成一个SQL字符串,如下所示:
string
...然后将SQL发送到数据库,结果转换为一堆IQuerable<>
s。这非常强大,允许您编写正常的C#代码,并将其解释为具有不同的含义,具体取决于提供商使{{1}}可供您使用。
答案 1 :(得分:1)
我相信,IQueryable用于数据库查询。您也无法在IQueryable中使用方法。
IEnumerable只是可以枚举的一些。就像列表或数组一样。
的IQueryable:
_repository.All<MyModel>(); // can return a IQueryable from the database.
例如,你不能在里面有一个方法,如果ID是GUID属性,你就不能这样做:
_repository.All<MyModel>(x => x.Id.ToString());
但是,IEnumerable是任何类型的List或Array,并且可以在其中使用方法。
来自MSDN的IQueryable:
提供评估针对特定数据源的查询的功能,其中数据的类型是已知的。
来自MSDN的IEnumerable:
公开一个枚举器,它支持对非泛型集合的简单迭代。
答案 2 :(得分:1)
这两者之间存在很大差异。实体框架使用 DbSet ,以便将linq的抽象暴露给数据库表。此曝光以 IQueryable 的形式出现。 IQueryable实现IEnumerable接口,并允许枚举查询结果到数据库。
枚举强制执行与IQueryable对象关联的表达式树 -MSDN:http://msdn.microsoft.com/en-us/library/vstudio/bb351562(v=vs.100).aspx
基本上IEnumerable只是对枚举所涉及的一组公开方法的引用。您可以在 MSDN: IEnumerable 中查看完整列表。
使用IQueryable对象通常意味着对活动数据库连接的引用。一旦处理了基础连接,任何尝试发出查询都将引发异常。因此,确保永远不会将IQueryable对象发送到视图或通过控制器非常重要。
可以使用.ToList()
调用或.First()
,.Single()
等强制枚举,这会强制查询信息。