【问题标题】:c# Understanding AsEnumerable in LINQ queryc# 了解 LINQ 查询中的 AsEnumerable
【发布时间】:2015-01-17 20:13:26
【问题描述】:

以下代码:

var mids = _db.Members
     .GroupBy(m => new { m.MemberID, m.CreatedDate })
     .Where(m => m.All(s => s.Status == 1) && m.Key.CreatedDate.Date == DateTime.Today)
     .Select(m=>m);

我收到运行时错误:LINQ to Entities 不支持指定的类型成员“日期”。仅支持初始化器、实体成员和实体导航属性

当我将 _db.Members.AsEnumerable() 添加到第一行时,它会起作用。

我的理解是 .AsEnumerable() 强制查询在客户端执行。因此,在上面的代码中,AsEnumerable 运算符将查询分为两部分,在服务器端选择并在客户端(分组依据、位置)休息。

有人可以验证我的理解是否正确吗?以及为什么没有 .AsEnumerable() 代码会失败?

【问题讨论】:

  • 是的,你是对的。另一方面,您不能使用 linq to sql 语法比较日期

标签: c# linq


【解决方案1】:

你的理解是正确的。调用AsEnumerable 后,无法再查询数据源并退回到简单的“给我一切”模式,这意味着所有数据都被传输到客户端并完成任何进一步的操作本地。

这也是查询不能按书面形式工作的原因:为了使其工作,您在 LINQ 方法中使用的所有表达式都必须可以翻译成您的数据源可以理解的任何语言——因为它是query provider 负责翻译,你也将受到它所支持的任何东西的限制。

在这种特定情况下(假设为 EF),可以通过手动替换对规范函数 TruncateTime 的属性访问来修复查询以在可查询模式下工作:

.Where(m => m.All(s => s.Status == 1) 
    && EntityFunctions.TruncateTime(m.Key.CreatedDate) ==
       EntityFunctions.TruncateTime(CurrentDateTime()))

【讨论】:

  • 不是 LINQ2Entities 吗? Ben 的帖子中提到了这一点。
  • 感谢乔恩的解释。因此,如果使用 EF,您会建议使用您的方法,因为条件将在数据源上执行,它会在服务器端执行?正确的?如果使用 AsEnumerable,它会返回所有信息,并会返回其他信息……更多可能无用的数据。
  • @Landeeyo EntityFunctions 适用于任何基于“实体”的系统,Linq2Entitys 和 EF 都是。重要的是您的提供者知道如何理解函数调用(默认提供者会这样做)。
  • @Ben 是的,如果你能做到的话,在服务器上执行是你一直想做的事情。
  • 你能分享一个我会使用 .AsEnumerable 的场景吗?如果你知道一篇好文章,请分享。感谢您的帮助。
【解决方案2】:

AsEnumerable 在您想要切换到 LINQ to Objects 时经常使用,主要是因为您想要使用 Linq to Entities 的一些功能不支持。当您使用AsEnumerable() 时,您将转换为IEnumerable<T>,它基本上将处理从数据源(包含所有数据和索引等)转移到您的应用程序。换句话说,如果您不使用 AsEnumerable()LINQ to Entities 会将您的查询转换为 SQL,并在您的数据源中远程执行。如果您想查看有关此主题的更多信息,我建议您阅读此post

正如 Jon 所说,Entity Framework 提供了一组函数用于处理可以直接转换为 SQL 的日期,这些函数位于 EntityFunctions 命名空间中。这些映射到所谓的“规范函数”,这意味着对 SQL 有 1:1 的翻译

【讨论】:

    猜你喜欢
    • 2011-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多