我试图理解IQueryable、ICollection、IList和IDictionary接口之间的差异,哪个更适合基本操作,如迭代、索引、查询等。
在使用这些接口时,像Collection、List、Dictionary等类应该是很好的选择。使用这些类的基本优势。
我尝试阅读其他类似问题的帖子,但没有一个完整地回答了我的问题。感谢您的帮助。
我试图理解IQueryable、ICollection、IList和IDictionary接口之间的差异,哪个更适合基本操作,如迭代、索引、查询等。
在使用这些接口时,像Collection、List、Dictionary等类应该是很好的选择。使用这些类的基本优势。
我尝试阅读其他类似问题的帖子,但没有一个完整地回答了我的问题。感谢您的帮助。
IEnumerable
,你应该确保你理解了这个接口。这个接口基本上允许您在C#的foreach
语句中使用类。
ICollection
是您列出的接口中最基本的接口。它是一个可枚举的接口,支持计数功能。IList
包括 ICollection
的所有功能,并且还支持添加和删除项目,通过索引检索项目等。它是“对象列表”最常用的接口,虽然这个说法有点模糊。IQueryable
是一种支持LINQ的可枚举接口。您可以始终从IList
创建一个IQueryable
并使用LINQ to Objects,但您还会在LINQ to SQL和LINQ to Entities中使用IQueryable
来延迟执行SQL语句。IDictionary
是一种不同类型的接口,它是将唯一键映射到值的集合。虽然您可以枚举键/值对,但它提供的功能与其他列出的接口有所不同。我注意到 gunny229 的答案 中存在一些问题。我已经在他的帖子评论区中提到了这些问题。后来,我想写一篇更详细的文章来连接一些遗漏的内容。
免责声明: 我并不打算完全满足 OP 的问题,但我想指出在使用 LINQ to SQL 时 IQueryable 和 IEnumerable 的区别。
我在数据库中创建了以下结构(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表中获取前两条记录。我在Visual Studio(VS)中创建了一个新的C#控制台应用程序,然后添加了指向数据库中Employee表的ADO.NET Entity Data Model XML(EDMX)项。现在我可以开始编写LINQ查询。
情况I: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 查询分析器的会话。以下是执行的摘要:
Total number of queries fired: 1
Query text:
SELECT TOP (2) [c].[Salary] AS [Salary] FROM [dbo].[Employee] AS [c]
Top (2)
子句。 因此,它仅通过网络传输其中的 2 条记录,而不需要在客户端进行任何内存过滤。
案例 II: 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);
}
}
本案执行概述:
Total number of queries fired: 1
Query text captured in SQL profiler:
SELECT [Extent1].[Salary] AS [Salary] FROM [dbo].[Employee] AS [Extent1]
需要注意的是,IEnumerable 从 Salary 表中获取了所有5条记录,然后在客户端执行内存过滤以获得前2条记录。因此,更多的数据(在此情况下为3条额外记录)被传输到网络上,并且不必要地占用了带宽。
IQueryable、IList、IDictionary、ICollection都继承自IEnumerable接口。所有类型集合的接口都将继承IEnumerable接口。
IEnumerable和IQueryable之间的区别 IEnumerable:当您运行返回IEnumerable类型的查询时,IEnumerable会先执行第一个查询,然后执行为该查询编写的子查询。
示例:如果您想从特定国家获取前10个人口记录,则在LINQ中使用的查询如下:
IEnumerable<LongInt> _Population=from s in India select s.population;//First Query
_Population=_Population.take(10);//Second Query
IQueryable<LongInt> _Population=from s in India select s.population;//First Query
_Population=_Population.take(10);//Second Query
Take
定义在IEnumerable<T>
上,我验证了在IEnumerable
和IQueryable
两种情况下只有1个查询被触发。只是IEnumerable
进行内存过滤,这会将不需要的数据带到网络上。 - RBT