带内连接的LINQ SUM:如何获得TimeSpan的总和

时间:2013-12-02 12:25:14

标签: c# sql linq

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

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表达式转换为type 'System.Linq.Expressions.LambdaExpression',因为它不是 代表类型 无法将lambda表达式转换为委托类型 'System.Func'因为某些返回类型 在块中不能隐式转换为委托返回 类型 无法将类型'System.TimeSpan'隐式转换为'int'

如果我用其他任何int,double或decimal类型替换WorkHours列(属性),那么一切正常。只有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);
}

1 个答案:

答案 0 :(得分:1)

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

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

因为Sum不接受IEnumerable<TimeSpan>的重载,所以请查看IEnumerable.Sum

编辑:

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

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();