Search code examples
c#linqlambdadatatablelinq-to-entities

c# DataTable Linq Group by Multiple column sum int and timespan


I want to sum of all Volume & TotalTimes Column after Group BY from DataTable Alias as Temp_DT. Remember Volume & All TotalTimes Column may have null or blank value. Can anyone help me to get the code through Linq Method

Sample Temp_DT:

enter image description here

Result should be in this format enter image description here

I have tried the below code, but Temp_DT result is Null.

var Temp_DT = tempdt.AsEnumerable().Select(x =>
                    new
                    {
                        UID = x.Field<string>("UID"),
                        EMPNAME = x.Field<string>("Emp Name"),
                        EMPROLE = x.Field<string>("Role"),
                        SUPID = x.Field<string>("Sup ID"),
                        SUPNAME = x.Field<string>("Sup Name"),
                        DESIGNATION = x.Field<string>("Designation"),
                        VOLUME = x.Field<int>("Volume"),
                        LOGINTIME = x.Field<TimeSpan>("Login Time"),
                        BREAKTIME = x.Field<TimeSpan>("Break Time"),
                        HANDLETIME = x.Field<TimeSpan>("Handle Time"),
                        ACTIVETIME = x.Field<TimeSpan>("Active Time"),
                        HOLDTIME = x.Field<TimeSpan>("Hold Time"),
                        ACWTIME = x.Field<TimeSpan>("ACW"),
                        IDLETIME = x.Field<TimeSpan>("Idle"),
                        PRODUCTIVE = x.Field<TimeSpan>("Productive"),
                        NONPRODUCTIVE = x.Field<TimeSpan>("Non Productive"),
                        USERERROR = x.Field<TimeSpan>("User Error Time")
                    }).GroupBy(s => new { s.UID, s.EMPNAME, s.EMPROLE, s.SUPID, s.SUPNAME, s.DESIGNATION })
                    .Select(g => new
                    {
                        g.Key.UID,
                        g.Key.EMPNAME,
                        g.Key.EMPROLE,
                        g.Key.SUPID,
                        g.Key.SUPNAME,
                        g.Key.DESIGNATION,
                        VOLUME = g.Sum(x => Convert.ToInt16(x.VOLUME)),
                        LOGINTIME = new TimeSpan(g.Sum(x => x.LOGINTIME.Ticks)),
                        BREAKTIME = new TimeSpan(g.Sum(x => x.BREAKTIME.Ticks)),
                        HANDLETIME = new TimeSpan(g.Sum(x => x.HANDLETIME.Ticks)),
                        ACTIVETIME = new TimeSpan(g.Sum(x => x.ACTIVETIME.Ticks)),
                        HOLDTIME = new TimeSpan(g.Sum(x => x.HOLDTIME.Ticks)),
                        ACWTIME = new TimeSpan(g.Sum(x => x.ACWTIME.Ticks)),
                        IDLETIME = new TimeSpan(g.Sum(x => x.IDLETIME.Ticks)),
                        PRODUCTIVE = new TimeSpan(g.Sum(x => x.PRODUCTIVE.Ticks)),
                        NONPRODUCTIVE = new TimeSpan(g.Sum(x => x.NONPRODUCTIVE.Ticks)),
                        USERERROR = new TimeSpan(g.Sum(x => x.USERERROR.Ticks)),
                    });

Solution

  • You have to Parse the TimeSpan and Sum by using Ticks, like below.

    var Temp_DT = tempdt.AsEnumerable().Select(x =>
                        new
                        {
                            UID = x["UID"],
                            EMPNAME = x["Emp Name"],
                            EMPROLE = x["Role"],
                            SUPID = x["Sup ID"],
                            SUPNAME = x["Sup Name"],
                            DESIGNATION = x["Designation"],
                            VOLUME = x["Volume"],
                            ERRORTIME = x["Error_Time"],                            
                            ACWTIME = x["ACW"],
                            BREAKTIME = x["Break Time"],
                            IDLETIME = x["Idle"],
                            NONPRODUCTIVE = x["Non Productive"],
                        }).GroupBy(s => new { s.UID, s.EMPNAME, s.EMPROLE, s.SUPID, s.SUPNAME, s.DESIGNATION })
                        .Select(g => {
                          var grouped = g.ToList();
                          return new
                          {
                              UID = g.Key.UID,
                              EMPNAME = g.Key.EMPNAME,
                              EMPROLE = g.Key.EMPROLE,
                              SUPID = g.Key.SUPID,
                              SUPNAME = g.Key.SUPNAME,
                              DESIGNATION = g.Key.DESIGNATION,
                              VOLUME = grouped.Sum(x => Convert.ToInt16(x.VOLUME)),
                              Error_Time = new TimeSpan(grouped.Select(x => ConvertTimeSpan(x.ERRORTIME.ToString())).ToList().Sum(r=> r.Ticks)),
                              ACW = new TimeSpan(grouped.Select(x => ConvertTimeSpan(x.ACWTIME.ToString())).ToList().Sum(r=> r.Ticks)),
                              Break = new TimeSpan(grouped.Select(x => ConvertTimeSpan(x.BREAKTIME.ToString())).ToList().Sum(r=> r.Ticks)),
                              Idle = new TimeSpan(grouped.Select(x => ConvertTimeSpan(x.IDLETIME.ToString())).ToList().Sum(r=> r.Ticks)),
                              NonProductive = new TimeSpan(grouped.Select(x => ConvertTimeSpan(x.NONPRODUCTIVE.ToString())).ToList().Sum(r=> r.Ticks))
                          };
                        }).ToList();
    

    The Conversion method is,

    private static TimeSpan ConvertTimeSpan(string str)
    {
       TimeSpan outputValue; 
       TimeSpan.TryParse(str, out outputValue);
    
       return outputValue;
    }
    

    C# Fiddle with sample data.