代码之家  ›  专栏  ›  技术社区  ›  Mike Fielden

理解LINQ to SQL中的.AsEnumerable()

  •  44
  • Mike Fielden  · 技术社区  · 14 年前

    给定以下LINQ到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
    

    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子句。

    这是否意味着整个“Imports”表被缓存到内存中?

    帮我理解幕后到底发生了什么。

    4 回复  |  直到 14 年前
        1
  •  39
  •   d219    5 年前

    原因 AsEnumerable 是到

    可用于在查询之间进行选择 实现IEnumerable(T),但也有 另一组公共查询 可用方法

    Where 方法之前,您正在调用另一个 在哪里? 方法从 IEnumerable.Where 在哪里? 语句用于LINQ转换为SQL IEnumerable 一个需要 ,枚举它并生成匹配项。这就解释了为什么会生成不同的SQL。该表将在 扩展将应用于代码的第二个版本。这可能会造成严重的瓶颈,因为整个表必须在内存中,或者更糟的是,整个表必须在服务器之间传输。允许SQL server执行 在哪里? 做它最擅长的事。

        2
  •  8
  •   Jon Hanna    14 年前

    在枚举通过的地方,将查询数据库,并检索整个结果集。

    部分和部分的解决方案可以是一种方法。考虑

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

    我们还假设nondatabaseconvertablecriteria需要result中的字段C。因为nondatabaseconvertablecriteria执行其名称所暗示的操作,所以必须作为枚举执行。但是,请考虑:

    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时,将向数据库传递尽可能多的工作,数据库将返回足够的工作以继续作业。假设确实不可能重写,以便所有工作都可以发送到数据库,这可能是一个合适的折衷方案。

        3
  •  5
  •   Jodrell    9 年前

    有三种实现 AsEnumerable .

    DataTableExtensions.AsEnumerable

    扩展 DataTable 给它一个 IEnumerable 数据表 .

    Enumerable.AsEnumerable<TSource> ParallelEnumerable.AsEnumerable<TSource>

    AsEnumerable<TSource>(IEnumerable<TSource>) 而不是将源代码的编译时类型从 工具 IEnumerable<T> IEnumerable<T>

    可计算的<t来源>(IEnumerable<TSource>) 可用于选择 IEnumerable<T> 但也有一组不同的公共查询方法 可用。例如,给定一个泛型类 Table IEnumerable<T> 有自己的方法,比如 Where Select ,和 SelectMany ,呼叫 会引起公众的注意 在哪里? . A 在哪里? 方法,该方法将谓词参数作为表达式树 并将树转换为SQL以便远程执行。如果远程执行 不需要,例如,因为谓词调用本地 方法 AsEnumerable<TSource> 自定义方法,而不是使用标准查询运算符 可用。

    如果我有

    IQueryable<X> sequence = ...;
    

    从LinqProvider,比如实体框架,我是这样做的,

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

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

    如果我想让它用Linq to Objects来运行语句,

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

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

    一些不寻常的预言 ,我的函数将直接使用(但是,这可能是一种低效的方法,因为所有行都将从服务器返回。)

        4
  •  2
  •   Razvi    14 年前

    我相信AsEnumerable只是告诉编译器要使用哪些扩展方法(在本例中是为IEnumerable定义的方法,而不是为IQueryable定义的方法)。