C# 返回IEnumerable<;T>;与IQueryable相比<;T>;
返回C# 返回IEnumerable<;T>;与IQueryable相比<;T>;,c#,linq,linq-to-sql,ienumerable,iqueryable,C#,Linq,Linq To Sql,Ienumerable,Iqueryable,返回IQueryable与返回IEnumerable之间有什么区别,什么时候应该优先选择其中一个 IQueryable<Customer> custs = from c in db.Customers where c.City == "<City>" select c; IEnumerable<Customer> custs = from c in db.Customers where c.City == "<City&g
IQueryable
与返回IEnumerable
之间有什么区别,什么时候应该优先选择其中一个
IQueryable<Customer> custs = from c in db.Customers
where c.City == "<City>"
select c;
IEnumerable<Customer> custs = from c in db.Customers
where c.City == "<City>"
select c;
IQueryable custs=来自数据库中的c客户
其中c.City==“”
选择c;
IEnumerable custs=来自c的数据库客户
其中c.City==“”
选择c;
两者都将被延迟执行,什么时候应该选择其中一个而不是另一个?两者都将为您提供延迟执行,是的
IQueryable<Customer> custs = from c in db.Customers
where c.City == "<City>"
select c;
IEnumerable<Customer> custs = from c in db.Customers
where c.City == "<City>"
select c;
至于哪个是首选的,这取决于您的底层数据源是什么
返回IEnumerable
将自动强制运行时使用LINQ to对象查询您的集合
返回一个IQueryable
(顺便说一句,它实现了IEnumerable
)提供了额外的功能,可以将查询转换为可能在底层源代码(LINQ到SQL、LINQ到XML等)上执行得更好的内容。是的,这两种方法都可以为您提供
区别在于,这个接口允许LINQ-to-SQL(LINQ.-to-anything)工作。因此,如果您进一步细化对的查询,那么如果可能,该查询将在数据库中执行
对于这种情况,它将是LINQtoObject,这意味着所有与原始查询匹配的对象都必须从数据库加载到内存中
代码:
IQueryable<Customer> custs = ...;
// Later on...
var goldCustomers = custs.Where(c => c.IsGold);
IQueryable客户=。。。;
//后来。。。
var goldCustomers=custs.Where(c=>c.IsGold);
该代码将执行SQL以仅选择黄金客户。另一方面,以下代码将在数据库中执行原始查询,然后过滤掉内存中的非黄金客户:
IEnumerable<Customer> custs = ...;
// Later on...
var goldCustomers = custs.Where(c => c.IsGold);
IEnumerable客户=。。。;
//后来。。。
var goldCustomers=custs.Where(c=>c.IsGold);
这是一个非常重要的区别,在许多情况下,处理可以避免从数据库返回太多行。另一个主要的例子是分页:如果使用and on,则只会得到请求的行数;在上执行此操作将导致将所有行加载到内存中。一般来说,我建议如下:
- Return
如果您想让开发人员使用您的方法在执行之前优化您返回的查询IQueryable
- 如果要传输一组要枚举的对象,请返回
IEnumerable
设想一个
IQueryable
就是这样一个数据“查询”(如果愿意,可以对其进行细化)。IEnumerable
是一组对象(已接收或已创建),您可以对其进行枚举。通常,您希望保留查询的原始静态类型,直到它起作用为止
因此,您可以将变量定义为“var”,而不是IQueryable
或IEnumerable
,这样您就知道您没有更改类型
如果您从一个IQueryable
开始,通常希望将其保留为IQueryable
,直到有令人信服的理由更改它。原因是您希望向查询处理器提供尽可能多的信息。例如,如果您只打算使用10个结果(您已经调用了Take(10)
),那么您希望SQL Server了解这一点,以便它能够优化其查询计划并只向您发送您将使用的数据
将类型从
IQueryable
更改为IEnumerable
的一个令人信服的原因可能是,您正在调用某个扩展函数,该函数在特定对象中的IQueryable
实现无法处理或处理效率低下。在这种情况下,您可能希望将该类型转换为IEnumerable
(例如,通过指定类型为IEnumerable
的变量,或使用AsEnumerable
扩展方法)因此,您调用的扩展函数最终是可枚举
类中的函数,而不是可查询
类。我最近遇到了IEnumerable
v的问题<代码>IQueryable。正在使用的算法首先执行IQueryable
查询以获得一组结果。然后将这些项传递给foreach
循环,并将这些项实例化为实体框架(EF)类。然后在Linq to实体查询的from
子句中使用该EF类,导致结果为IEnumerable
我对实体的EF和Linq相当陌生,所以花了一段时间才弄清楚瓶颈是什么。使用miniprofileing,我找到了查询,然后将所有单个操作转换为单个IQueryable
linqforentities查询。执行IEnumerable
需要15秒,执行IQueryable
需要0.5秒。这涉及到三个表,在阅读本文之后,我相信IEnumerable
查询实际上形成了一个三表叉积并过滤结果
尝试使用IQueryables作为经验法则,并分析您的工作,使您的更改可以测量。有一篇博客文章,其中提供了简短的源代码示例,介绍了误用
IEnumerable
会如何显著影响LINQ查询性能:
如果我们深入挖掘并查看源代码,我们可以看到,IEnumerable
显然有不同的扩展方法:
products.Skip(-4);
//类型:System.Linq.Enumerable
//程序集:System.Core,版本=4.0.0.0,区域性=neutral,PublicKeyToken=b77a5c561934e089
//程序集位置:C:\Windows\Microsoft.NET\Framework\v4.0.30319\System.Core.dll
公共静态类可枚举
{
公共静态IEnumerable在哪里(
这是一个数不清的来源,
Func谓词)
{
返回(IEnumerable)
新的可枚举。WhereEnumerableInterator(源,谓词);
}
}
和iquiry
MarketDevEntities db = new MarketDevEntities();
IEnumerable<WebLog> first = db.WebLogs;
var second = first.Where(c => c.DurationSeconds > 10);
var third = second.Where(c => c.WebLogID > 100);
var result = third.Where(c => c.EmailAddress.Length > 11);
Console.Write(result.First().UserName);
"SELECT * FROM [dbo].[WebLog]"
"SELECT TOP 1 * FROM [dbo].[WebLog] WHERE [DurationSeconds] > 10 AND [WebLogID] > 100 AND LEN([EmailAddress]) > 11"
products.Skip(-4);
SELECT [p].[ProductId]
FROM [Products] AS [p]
ORDER BY (SELECT 1)
OFFSET @__p_0 ROWS