【问题标题】:LINQ SUM with Inner Joins: How to get the Sum for a TimeSpan带有内部连接的 LINQ SUM:如何获取 TimeSpan 的总和
【发布时间】:2013-12-02 12:25:14
【问题描述】:

我一直在尝试使用 LINQ 重写以下 SQL 查询,我设法做到了如下:

SQL

select 
    u.FirstName, 
    u.ExpectedWeeklyHours, 
    sum(t.TimeSpent)  -- SQL DataType is Time(7)

from dbo.Users u 
    inner join 
    dbo.Times t 
    on u.UserID = t.UserId
group by u.FirstName, 
         u.ExpectedWeeklyHours

LINQ

using (var data = new DAL())
{
    var result =
        (from times in data.Times
            join users in data.Users on times.UserId equals users.UserID
            select new
            {
                UserName = users.FirstName + " " + users.LastName, 
                ExpectedHours = users.ExpectedWeeklyHours, 
                WorkHours = times.TimeSpent
            } into x
            group x by new
            {
                UserName = x.UserName,
                ExpectedWorkingHours = x.ExpectedHours
            }
            into g
            select new
            {
                UserName = g.Key.UserName,
                ExpectedWorkingHours = g.Key.ExpectedWorkingHours,
                TotalWorkingHours = g.Sum(i=>i.WorkHours)
            }
            ).ToList();
}

我的问题是 WorkHours 的类型为:TimeSpan,我收到以下(编译时间)错误:

  • 无法将 lambda 表达式转换为类型 'System.Linq.Expressions.LambdaExpression' 因为它不是 委托类型 无法将 lambda 表达式转换为委托类型 'System.Func' 因为一些返回类型 块中的不能隐式转换为委托返回 类型 无法将类型“System.TimeSpan”隐式转换为“int”

如果我将 WorkHours 列(属性)替换为任何其他类型的 int、double 或 decimal,则一切正常。只是Linq的SUM函数不支持TimeSpan!

你能帮忙吗,提前谢谢你..

编辑

根据以下 wuzdik 提出的建议,我来到了这个问题的解决方案,我分享它以帮助有需要的人:

 using (var data = new DAL())
{
    var result =
        (from times in data.Times
            join users in data.Users on times.UserId equals users.UserID
            select new
            {
                UserID = users.UserID,
                UserName = users.FirstName + " " + users.LastName,
                ExpectedHours = users.ExpectedWeeklyHours,
                WorkHours = times.TimeSpent
            }
            into x
            group x by new
            {
                UserId = x.UserID,
                UserName = x.UserName,
                ExpectedWorkingHours = x.ExpectedHours
            }).AsEnumerable().ToList();

    var finale = (from p in result
        select new TimeModelDashboard
        {
            UserId = p.Key.UserId,
            UserName = p.Key.UserName,
            ExpectedWorkingHours = p.Key.ExpectedWorkingHours,
            TotalWorkingHours = (decimal) p.Sum(t => t.WorkHours.TotalHours)
        }).ToList();

    return Json(finale);
}

【问题讨论】:

    标签: c# sql linq


    【解决方案1】:

    您需要创建新的TimeSpan = 时间跨度的总和

    TotalWorkingHours = new TimeSpan(g.Sum(w => w.WorkHours.Ticks));
    

    因为 Sum 并没有超载接受 IEnumerable<TimeSpan>,所以请看这里 IEnumerable.Sum

    编辑:

    尝试更快地实现查询,这样new Timespan 将在 Linq 中被调用到对象

    var result =
        (from times in data.Times
            join users in data.Users on times.UserId equals users.UserID
            select new
            {
                UserName = users.FirstName + " " + users.LastName, 
                ExpectedHours = users.ExpectedWeeklyHours, 
                WorkHours = times.TimeSpent
            } into x
            group x by new
            {
                UserName = x.UserName,
                ExpectedWorkingHours = x.ExpectedHours
            }
            into g
        ).AsEnumerable().Select(new {
                UserName = g.Key.UserName,
                ExpectedWorkingHours = g.Key.ExpectedWorkingHours,
                TotalWorkingHours = new TimeSpan(g.Sum(w => w.WorkHours.Ticks))
          }.ToList();
    

    【讨论】:

    • 我已经尝试了上述方法,但没有成功。我收到此错误消息:LINQ to Entities 中仅支持无参数构造函数和初始化程序。
    • @t_plusplus 尝试更快地对查询进行金属化,正如我在 EDIT 中建议的那样
    • 感谢您提出的更快实现查询的建议,我已在上面的编辑中对此进行了最后的练习。亲切的问候。
    猜你喜欢
    • 2013-10-26
    • 2021-12-08
    • 2021-03-29
    • 1970-01-01
    • 1970-01-01
    • 2021-04-26
    • 2013-09-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多