c#了解LINQ查询中的AsEnumerable

时间:2015-01-17 20:13:27

标签: c# linq

代码如下:

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运算符将查询转换为2部分在服务器端选择并在客户端休息(group by,where)。

如果我的理解是正确的,有人可以验证吗?以及没有.AsEnumerable()的代码失败的原因?

2 个答案:

答案 0 :(得分:4)

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

这也是为什么查询不能按原样运行的原因:为了使它能够工作,你在LINQ方法中使用的所有表达式都必须可以翻译成数据源所理解的任何语言 - 因为它是query provider负责进行翻译,你也会受到编程支持的任何限制。

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

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

答案 1 :(得分:2)

当你想切换到 LINQ to Objects 时经常使用

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

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