给定以下 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 子句。

这是否意味着整个“导入”表都缓存到内存中?如果表包含大量记录,性能会降低吗?

帮助我了解幕后实际发生的事情。

有帮助吗?

解决方案

的原因 作为可枚举的 是为了

可调(tsource)(iEnumerable(tsource))可用于在查询实现之间进行选择,当序列实现iEnumerable(t),但也具有不同的公共查询方法

所以当你打电话给 Where 之前的方法,你调用了不同的 Where 方法从 IEnumerable.Where. 。那 Where 语句用于将 LINQ 转换为 SQL,新的 Where 是个 IEnumerable 一个需要一个 IEnumerable, ,枚举它并生成匹配项。这解释了为什么您会看到生成不同的 SQL。该表将在执行之前从数据库中完整获取 Where 扩展将应用于您的第二个版本的代码中。这可能会造成严重的瓶颈,因为整个表必须位于内存中,或者更糟糕的是,整个表必须在服务器之间传输。允许SQL服务器执行 Where 并做它最擅长的事情。

其他提示

在枚举枚举的位置,然后将验证数据库,并检索整个结果集。

部分和部分解决方案可以是方式。考虑

var res = (
    from result in SomeSource
    where DatabaseConvertableCriterion(result)
    && NonDatabaseConvertableCriterion(result)
    select new {result.A, result.B}
);
.

让我们也可以说NondatabaseConvertableSigerion需要Field C.因为NondatabaseConvertableSeCerion是它的名字所建议的,因此必须作为枚举执行。但是,考虑:

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}
);
. 在这种情况下,当res枚举,查询或以其他方式使用时,尽可能多的工作将传递给数据库,这将返回足以继续作业。假设它确实无法重写使得所有工作都可以发送到数据库,这可能是一个合适的妥协。

有以下三种实现方式 AsEnumerable.

DataTableExtensions.AsEnumerable

扩展了一个 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. 。A Table 表示数据库表的类型可以有 Where 将谓词参数作为表达树并将树转换为SQL以进行远程执行的方法。例如,如果不需要远程执行,例如,因为谓词调用了本地方法,则 AsEnumerable<TSource> 方法可用于隐藏自定义方法,而是使标准查询运算符可用。

换句话说。

如果我有一个

IQueryable<X> sequence = ...;

来自 LinqProvider,例如实体框架,我这样做,

sequence.Where(x => SomeUnusualPredicate(x));

该查询将在服务器上编写并运行。这将在运行时失败,因为 EntityFramework 不知道如何转换 SomeUnusualPredicate 进入 SQL。

如果我希望使用 Linq to Objects 来运行该语句,我会这样做,

sequence.AsEnumerable().Where(x => SomeUnusualPredicate(x));

现在服务器将返回所有数据和 Enumerable.Where 将使用 Linq to Objects 来代替查询提供程序的实现。

实体框架不知道如何解释也没关系 SomeUnusualPredicate, ,我的函数将直接使用。(但是,这可能是一种低效的方法,因为所有行都将从服务器返回。)

我相信Asenuble只是告诉编译器要使用的扩展方法(在这种情况下为IEnumerable定义的,而不是iQueryable)。 在调用toArray或枚举之前,仍会延迟查询的执行。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top