IQueryable、ICollection、IList 和 IDictionary 接口之间的区别
Posted
技术标签:
【中文标题】IQueryable、ICollection、IList 和 IDictionary 接口之间的区别【英文标题】:Difference between IQueryable, ICollection, IList & IDictionary interface 【发布时间】:2011-05-26 05:18:11 【问题描述】:我想了解 这对于迭代、索引、查询等基本操作更快。
Collection、List、Dictionary 等哪个类适合使用这些接口进行初始化,以及我们应该何时使用这些类。与其他类相比,使用这些类的基本优势。
我尝试阅读其他有类似问题的帖子,但没有人回答我的全部问题。 感谢您的帮助。
【问题讨论】:
【参考方案1】:所有这些接口都继承自 IEnumerable,您应该确保自己理解这一点。该接口基本上允许您在 foreach
语句中使用该类(在 C# 中)。
每一个的 MSDN 文档都很不错,所以我将从那里开始完善您的理解。
【讨论】:
+1 获取这些接口的详细说明,但您错过了我的其他问题 在接口的通用版本方面,ICollection我注意到上面@gunny229 的回答中有几个问题,这就是我写这篇文章的原因。我在他的帖子的评论区也提到了这些问题。为了更正那个帖子,我几乎不得不重写整个帖子,所以我想创建自己的帖子。我不打算完全解决 OP 的问题,但我想指出 使用 LINQ to SQL 时 IQueryable 和 IEnumerable 之间的区别。
我在 DB(DDL 脚本)中创建了以下结构:
CREATE TABLE [dbo].[Employee]([PersonId] [int] NOT NULL PRIMARY KEY,[Salary] [int] NOT NULL)
这里是记录插入脚本(DML脚本):
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(1, 20)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(2, 30)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(3, 40)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(4, 50)
INSERT INTO [EfTest].[dbo].[Employee] ([PersonId],[Salary])VALUES(5, 60)
GO
现在我的目标是简单地从数据库中的 Employee
表中获取前 2 条记录。因此,我在控制台应用程序中添加了一个 ADO.NET 实体数据模型项,指向数据库中的 Employee
表并开始编写 LINQ 查询。
IQueryable 路由代码:
using (var efContext = new EfTestEntities())
IQueryable<int> employees = from e in efContext.Employees select e.Salary;
employees = employees.Take(2);
foreach (var item in employees)
Console.WriteLine(item);
当我开始运行这个程序时,我还在我的 SQL Server 实例上启动了一个 SQL 查询分析器会话,这里是执行摘要:
-
触发的查询总数:1
查询文本:
SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] AS [c]
只是IQueryable
足够聪明,可以在数据库服务器端应用Top (2)
子句,因此它只通过网络传输5 条记录中的2 条。在客户端计算机端根本不需要任何进一步的内存过滤。
IEnumerable 路由代码:
using (var efContext = new EfTestEntities())
IEnumerable<int> employees = from e in efContext.Employees select e.Salary;
employees = employees.Take(2);
foreach (var item in employees)
Console.WriteLine(item);
本例执行总结:
-
触发的查询总数:1
在 SQL 分析器中捕获的查询文本:
SELECT [Extent1].[Salary] AS [Salary]
FROM [dbo].[Employee] AS [Extent1]
现在问题是IEnumerable
带来了Salary
表中存在的所有 5 条记录,然后在客户端计算机上执行内存过滤以获得前 2 条记录。因此,更多数据(在本例中为 3 条额外记录)不必要地通过网络传输。
【讨论】:
谢谢,但我不认为@gunny229 的回答具有误导性。是的,他使用了“查询”这个词,但这不是在数据库的上下文中。获得前两个只是另一个计算。至少我在阅读时是这样认为的。干杯。【参考方案3】:IQueryable,IList,IDictionary,ICollection 继承了 IEnumerable 接口。 类型集合的所有接口都会继承IEnumerable接口。
IEnumerable 和 IQueryable 之间的区别 IEnumerable:-当您运行返回 IEnumerable 类型的查询时。 IEnumerable 将首先执行第一个查询,然后执行为该查询编写的子查询。
示例:-如果您想获得来自特定国家/地区的前 10 名人口记录,那么我们将在 LinQ 中使用的查询是
IEnumerable _Population=from s in India select s.population;//第一次查询 _Population=_Population.take(10);//第二次查询
现在,如果我们执行这个查询 First Query 将首先执行,IEnumerable 将从 sql server 获取所有人口的记录,然后它将数据存储在 In Process 内存中,然后执行前 10 个人口下一个查询。(在sql server上执行两次)。
如果我们使用 IQueryable 执行相同的查询。
IQueryable _Population=from s in India select s.population;//第一次查询 _Population=_Population.take(10);//第二次查询
在这个 IQueryable 中,它将同时执行两个查询,因为它将获得单个查询中前 10 名的人口,而不是获取数据并再次过滤前 10 个。(一次执行sql 服务器)。
IQueryable 和 IEnumerable 的结论
-
如果您正在针对数据库中的数据编写查询,那么
使用 IQueryable。
如果您正在查询处理中的数据,那么
使用 IEnumerable。
IEnumerable 有 GetEnumerator()、Current() 和 MoveNext() 方法。
【讨论】:
很高兴知道其中的区别。 (y) 扩展方法Take
是在IEnumerable<T>
上定义的。我验证了 只有 1 查询在这两种情况下都会被触发,无论是IEnumerable
还是IQueryable
。只是IEnumerable
会进行内存过滤,这会将不需要的数据通过网络传输。以上是关于IQueryable、ICollection、IList 和 IDictionary 接口之间的区别的主要内容,如果未能解决你的问题,请参考以下文章
IList,ICollection,IEnumerable,IEnumerator,IQueryable
EF ICollection Vs List Vs IEnumerable Vs IQueryable
EF下怎么理解IEnumerable/ICollection/IQueryable?