了解 LINQ to SQL 中的 .AsEnumerable()
给定以下 LINQ to SQL 查询:
var test = from i in Imports
where i.IsActive
select i;
解释的 SQL 语句是:
SELECT [t0].[id] AS [Id] .... FROM [Imports] AS [t0] WHERE [t0].[isActive] = 1
假设我想在 select 中执行某些无法转换为 SQL 的操作。据我了解,实现此目的的传统方法是执行 AsEnumerable() ,从而将其转换为可用对象。
鉴于此更新的代码:
var test = from i in Imports.AsEnumerable()
where i.IsActive
select new
{
// Make some method call
};
和更新的 SQL:
SELECT [t0].[id] AS [Id] ... FROM [Imports] AS [t0]
请注意执行的 SQL 语句中缺少 where 子句。
这是否意味着整个“导入”表都缓存到内存中? 如果表包含大量记录,性能会降低吗?
帮助我了解幕后实际发生的事情。
Given the following LINQ to SQL query:
var test = from i in Imports
where i.IsActive
select i;
The interpreted SQL statement is:
SELECT [t0].[id] AS [Id] .... FROM [Imports] AS [t0] WHERE [t0].[isActive] = 1
Say I wanted to perform some action in the select that cannot be converted to SQL. Its my understanding that the conventional way to accomplish this is to do AsEnumerable()
thus converting it to a workable object.
Given this updated code:
var test = from i in Imports.AsEnumerable()
where i.IsActive
select new
{
// Make some method call
};
And updated SQL:
SELECT [t0].[id] AS [Id] ... FROM [Imports] AS [t0]
Notice the lack of a where clause in the executed SQL statement.
Does this mean the entire "Imports" table is cached into memory?
Would this slow performance at all if the table contained a large amount of records?
Help me to understand what is actually happening behind the scenes here.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
AsEnumerable 的原因是
因此,当您之前调用
Where
方法时,您是从IEnumerable.Where
调用不同的Where
方法。该Where
语句用于将 LINQ 转换为 SQL,新的Where
是采用IEnumerable
的IEnumerable
语句,枚举它并生成匹配项。这解释了为什么您会看到生成不同的 SQL。在将Where
扩展应用到代码的第二个版本中之前,将从数据库中完整获取该表。这可能会造成严重的瓶颈,因为整个表必须位于内存中,或者更糟糕的是,整个表必须在服务器之间传输。允许 SQL Server 执行Where
并执行其最擅长的操作。The reason for AsEnumerable is to
So when you were calling the
Where
method before, you were calling a differentWhere
method from theIEnumerable.Where
. ThatWhere
statement was for LINQ to convert to SQL, the newWhere
is theIEnumerable
one that takes anIEnumerable
, enumerates it and yields the matching items. Which explains why you see the different SQL being generated. The table will be taken in full from the database before theWhere
extension will be applied in your second version of the code. This could create a serious bottle neck, because the entire table has to be in memory, or worse the entire table would have to travel between servers. Allow SQL server to execute theWhere
and do what it does best.在枚举完成后,将查询数据库,并检索整个结果集。
部分解决方案可能是一种方法。考虑
一下,NonDatabaseConvertableCriterion 需要结果中的字段 C。因为 NonDatabaseConvertableCriterion 的作用正如其名称所示,所以必须作为枚举来执行。但是,请考虑:
在这种情况下,当枚举、查询或以其他方式使用 res 时,尽可能多的工作将传递到数据库,数据库将返回足够的内容来继续作业。假设确实不可能重写以便将所有工作发送到数据库,这可能是一个合适的折衷方案。
At the point where the enumeration is enumerated through, the database will then be queried, and the entire resultset retrieved.
A part-and-part solution can be the way. Consider
Let's say also that NonDatabaseConvertableCriterion requires field C from result. Because NonDatabaseConvertableCriterion does what its name suggests, this has to be performed as an enumeration. However, consider:
In this case, when res is enumerated, queried or otherwise used, as much work as possible will be passed to the database, which will return enough to continue the job. Assuming that it is indeed really impossible to rewrite so that all the work can be sent to the database, this may be a suitable compromise.
AsEnumerable
共有三种实现。DataTableExtensions.AsEnumerable
扩展
DataTable
以为其提供IEnumerable
接口,以便您可以针对DataTable 使用 Linq
。Enumerable.AsEnumerable< ;TSource>
和ParallelEnumerable.AsEnumerable
换句话说。
如果我有一个
来自 LinqProvider(例如实体框架)的查询,那么
该查询将在服务器上组合并运行。这将在运行时失败,因为 EntityFramework 不知道如何将
SomeUnusualPredicate
转换为 SQL。如果我希望使用 Linq to Objects 来运行语句,我会这样做,
现在服务器将返回所有数据,并且将使用 Linq to Objects 中的
Enumerable.Where
而不是查询提供程序的实现。实体框架不知道如何解释
SomeUnusualPredicate
没关系,我的函数将直接使用。 (但是,这可能是一种低效的方法,因为所有行都将从服务器返回。)There are three implementations of
AsEnumerable
.DataTableExtensions.AsEnumerable
Extends a
DataTable
to give it anIEnumerable
interface so you can use Linq against theDataTable
.Enumerable.AsEnumerable<TSource>
andParallelEnumerable.AsEnumerable<TSource>
In other words.
If I have an
from a LinqProvider, like Entity Framework, and I do,
that query will be composed and run on the server. This will fail at runtime because the EntityFramework doesn't know how to convert
SomeUnusualPredicate
into SQL.If I want that to run the statement with Linq to Objects instead, I do,
now the server will return all the data and the
Enumerable.Where
from Linq to Objects will be used instead of the Query Provider's implementation.It won't matter that Entity Framework doesn't know how to interpret
SomeUnusualPredicate
, my function will be used directly. (However, this may be an inefficient approach since all rows will be returned from the server.)我相信 AsEnumerable 只是告诉编译器要使用哪些扩展方法(在本例中是为 IEnumerable 定义的扩展方法,而不是为 IQueryable 定义的扩展方法)。
查询的执行仍然会延迟,直到您调用 ToArray 或对其进行枚举。
I believe the AsEnumerable just tells the compiler which extension methods to use (in this case the ones defined for IEnumerable instead of those for IQueryable).
The execution of the query is still deferred until you call ToArray or enumerate on it.