【问题标题】:How to group by day of week using linq如何使用 linq 按星期几分组
【发布时间】:2016-01-01 12:08:07
【问题描述】:

我正在尝试计算本周更新的一些记录,并按星期几对它们进行分组(取决于它们上次更新的时间)。例如,周二:1、周四:4 周五:5 等...我不知道如何按星期几分组。

var data = repo
    .Where(o => o.LastUpdated >= monday)
    .GroupBy(o => o.LastUpdated)
    .Select(g => new { DayOfWeek = g.Key, Count = g.Count() })
    .ToList();

我试过 .GroupBy(o => o.LastUpdated.DayOfWeek 但这会引发错误: "LINQ to Entities 不支持指定的类型成员 'DayOfWeek'"

【问题讨论】:

    标签: entity-framework linq


    【解决方案1】:

    消息是明确的,实体框架不知道如何将“DayOfWeek”翻译成 SQL。最简单的解决方案是在检索数据后在 SQL 之外进行分组:

    var data = repo
        .Where(o => o.LastUpdated >= monday)
        .AsEnumerable() // After this everything uses LINQ to Objects and is executed locally, not on your SQL server
        .GroupBy(o => o.LastUpdated)
        .Select(g => new { DayOfWeek = g.Key, Count = g.Count() })
        .ToList();
    

    无论哪种方式,它都不应该对性能产生影响,因为您没有进一步向下过滤,因此您不会从服务器检索到比您需要的更多的数据,任何超过 AsEnumerable 的数据都会被物化为数据,在生成 SQL 查询之前的任何数据,所以通过 AsEnumerable(或任何其他可以实现查询的东西,如 ToArray 或 ToList),您可以使用您通常在 C# 中使用的任何东西,而不必担心它会被翻译成 SQL。

    【讨论】:

    • 好的,我已经添加了 .AsEnumerable() 然后添加了 .GroupBy(o => o.LastUpdated.DayOfWeek) ...它已经工作了。
    • 根据这个 SO answer AsEnumerable 在 Where 子句之后不会将所有记录加载到内存中,而是加载所有列。因此,您可能需要验证这一点并更新您的答案。
    • @ThabisoMofokeng AsEnumerable 不加载任何东西,只有物化运算符(tolist、sum 等)会加载任何东西,它只是从使用 linq 切换到对象方法而不是 IQueryable 方法,并且这些方法在内存,所以在这种情况下,在 AsEnumerable 之后所做的任何事情都将在内存中完成。至于从数据库中加载的内容,无论您在 AsEnumerable 之后做什么,将加载的内容是在它之前已经物化的内容(与调用 tolist 相同,但执行延迟且没有列表),因此取决于是否使用惰性加载与否
    【解决方案2】:

    如果您只针对 SqlServer 数据库类型,则可以使用 SqlFunctions.DatePart 这样的规范函数

    var data = repo
        .Where(o => o.LastUpdated >= monday)
        .GroupBy(o => SqlFunctions.DatePart("weekday", o.LastUpdated))
        .Select(g => new { DayOfWeek = g.Key, Count = g.Count() })
        .ToList();
    

    不幸的是,DbFunctions 中没有定义这样的通用规范函数,因此如果您针对的是另一种数据库类型(或多种数据库类型),唯一的选择是切换到 Linq To Objects 上下文如another answer 中所述。

    【讨论】:

      【解决方案3】:

      只能 lastupdated 日期时间的列数据类型。

      var data = repo.Where(o => o.LastUpdated >= monday).AsEnumerable().GroupBy(o => o.LastUpdated.Value.Day).Select(g => new { DayOfWeek = g.Key, Count = g.Count() }).ToList();
      

      【讨论】:

        猜你喜欢
        • 2017-07-13
        • 2022-08-10
        • 2011-10-31
        • 1970-01-01
        • 2021-10-29
        • 1970-01-01
        • 1970-01-01
        • 2015-05-13
        • 2013-01-09
        相关资源
        最近更新 更多