Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/281.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 返回IEnumerable<;T>;与IQueryable相比<;T>;_C#_Linq_Linq To Sql_Ienumerable_Iqueryable - Fatal编程技术网

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