Mik*_*den 44 c# linq linq-to-sql asenumerable
给出以下LINQ to SQL查询:
var test = from i in Imports
where i.IsActive
select i;
Run Code Online (Sandbox Code Playgroud)
解释的SQL语句是:
SELECT [t0].[id] AS [Id] .... FROM [Imports] AS [t0] WHERE [t0].[isActive] = 1
Run Code Online (Sandbox Code Playgroud)
假设我想在select中执行一些无法转换为SQL的操作.我的理解是,实现这一目标的传统方法是AsEnumerable()将其转换为可行的对象.
鉴于此更新的代码:
var test = from i in Imports.AsEnumerable()
where i.IsActive
select new
{
// Make some method call
};
Run Code Online (Sandbox Code Playgroud)
并更新了SQL:
SELECT [t0].[id] AS [Id] ... FROM [Imports] AS [t0]
Run Code Online (Sandbox Code Playgroud)
注意执行的SQL语句中缺少where子句.
这是否意味着整个"Imports"表被缓存到内存中?如果表中包含大量记录,这会导致性能下降吗?
帮助我了解幕后实际发生的事情.
Yur*_*ich 34
AsEnumerable的原因是
当序列实现IEnumerable(T)但也有一组不同的公共查询方法时,AsEnumerable(TSource)(IEnumerable(TSource))可用于在查询实现之间进行选择
因此,当您之前调用Where方法时,您正在从IEnumerable.Where调用另一个Where方法.Where语句用于LINQ转换为SQL,新的Where是IEnumerable获取IEnumerable,枚举它并产生匹配项.这解释了为什么您看到生成的不同SQL.在您的第二版代码中应用Where扩展名之前,将从数据库中完整地获取该表.这可能会造成严重的瓶颈,因为整个表必须在内存中,或者更糟糕的是整个表必须在服务器之间传输.允许SQL Server执行Where并执行它最擅长的操作.
在枚举枚举的位置,将查询数据库,并检索整个结果集.
零件和零件解决方案可以是方式.考虑
var res = (
from result in SomeSource
where DatabaseConvertableCriterion(result)
&& NonDatabaseConvertableCriterion(result)
select new {result.A, result.B}
);
Run Code Online (Sandbox Code Playgroud)
我们还要说NonDatabaseConvertableCriterion要求结果中的字段C. 因为NonDatabaseConvertableCriterion就像它的名字所暗示的那样,所以必须以枚举的形式执行.但是,请考虑:
var partWay =
(
from result in SomeSource
where DatabaseConvertableCriterion(result)
select new {result.A, result.B, result.C}
);
var res =
(
from result in partWay.AsEnumerable()
where NonDatabaseConvertableCriterion select new {result.A, result.B}
);
Run Code Online (Sandbox Code Playgroud)
在这种情况下,当枚举,查询或以其他方式使用res时,尽可能多的工作将传递给数据库,该数据库将返回足以继续该作业的数据库.假设确实无法重写以便可以将所有工作发送到数据库,这可能是一个合适的折衷方案.
有三种实现方式AsEnumerable.
DataTableExtensions.AsEnumerable
扩展a DataTable以给它一个IEnumerable接口,这样你就可以使用Linq了DataTable.
Enumerable.AsEnumerable<TSource> 和 ParallelEnumerable.AsEnumerable<TSource>
AsEnumerable<TSource>(IEnumerable<TSource>)除了将源代码的编译时类型从实现的类型更改IEnumerable<T>为IEnumerable<T>自身之外,该方法没有任何效果.
AsEnumerable<TSource>(IEnumerable<TSource>)可用于在序列实现时在查询实现之间进行选择,IEnumerable<T>但也可以使用不同的公共查询方法集.例如,给定泛型类Table实现IEnumerable<T>,并有自己的方法,如Where,Select和SelectMany,调用Where将调用公共Where的方法Table.甲Table表示数据库表类型可以有一个Where,是以谓词参数作为表达式树并转换树到SQL远程执行的方法.如果不需要远程执行,例如因为谓词调用本地方法,则该AsEnumerable<TSource>方法可用于隐藏自定义方法,而是使标准查询运算符可用.
换一种说法.
如果我有
IQueryable<X> sequence = ...;
Run Code Online (Sandbox Code Playgroud)
来自LinqProvider,比如Entity Framework,我做的,
sequence.Where(x => SomeUnusualPredicate(x));
Run Code Online (Sandbox Code Playgroud)
该查询将在服务器上编写并运行.这将在运行时失败,因为EntityFramework不知道如何转换SomeUnusualPredicate为SQL.
如果我希望用Linq对象运行语句,我会这样做,
sequence.AsEnumerable().Where(x => SomeUnusualPredicate(x));
Run Code Online (Sandbox Code Playgroud)
现在服务器将返回所有数据,并且将使用Enumerable.Where从Linq到Objects的代替Query Provider的实现.
实体框架不知道如何解释并不重要SomeUnusualPredicate,我的功能将直接使用.(但是,这可能是一种低效的方法,因为所有行都将从服务器返回.)
| 归档时间: |
|
| 查看次数: |
35277 次 |
| 最近记录: |