使用LINQ从字符串日期按月分组

时间:2018-03-12 13:29:41

标签: asp.net-mvc entity-framework linq group-by

我按月GroupBy记录做了很多不必要的工作。在数据库中,日期以varchar格式保存,现在,我无法更改格式,因为很多东西都依赖于它。以下是我的代码:

var Job_Progress_ViewModel = new List<MyViewModel>();

var Job_Ids = new List<int?>();

var Jobs = db.Jobs.Where(x.Date != null).ToList();

foreach (var job in Jobs)
{
   int Year = Year_from_strDate(job.Date);
   if (Year == 2018)
   {
      Job_Ids .Add(order.Id);
   }
}

var JobProgress = db.JobProgress.Where(x => Job_Ids.Contains(x.JobId)).ToList();

foreach(var record in JobProgress)
{
   var Model = new MyViewModel()
   {
       Month = Month_From_strDate(record.Job.Date),
       Amount = record.total
   };
   Job_Progress_ViewModel.Add(Model);
}

在我的观点中:

foreach (var month in Model.Select(x=>x.Month).Distinct())
{
   <tr>
     <td>
        @Model.Where(x => x.Month == month).Sum(x => x.Amount))
     </td>
   </tr>
}

我不认为这是好方法。然后我在互联网上搜索,并尝试使用以下代码:

db.JobProgress.Where(x => Job_Ids.Contains(x.JobId))
.GroupBy(x => Month_From_strDate(x.Job.Date)
.Select(ln => new MyViewModel
{
   Month = // How can I add month Here,
   Amount = ln.Sum(r => r.total)
}).ToList();

我发现它更好的方法,但这里有两个问题:

  1. 我不知道如何获得月,
  2. 我不能使用日期转换功能。我收到以下有效的错误:
  3.   

    LINQ to Entities无法识别方法'System.String   的ToString()'

    我怎样才能解决这个问题,因为我无法更改数据库中的日期格式?

1 个答案:

答案 0 :(得分:0)

datetime作为varchar存储在数据库中是一个非常糟糕的主意。管理它们会非常困难,这会让你头疼,就像这个例子一样。因此,我强烈建议您不惜任何代价将其转换为datetime类型。

因此,在您的情况下,您可以尝试使用SqlFunctions.DateAdd使用varchardatetime解析为groupSqlFunctions.DatePart

db.JobProgress.Where(x => Job_Ids.Contains(x.JobId))
.GroupBy(x => SqlFunctions.DatePart("month", SqlFunctions.DateAdd("day", 0, x.Job.Date)))
.Select(ln => new MyViewModel
{
   Month = ln.Key
   Amount = ln.Sum(r => r.total)
}).ToList();

如果你在解析datetime时失败了,你应首先实现查询并按内存应用group,这种方法会很昂贵。

注意: SqlFunctions.DateAdd接受字符串日期参数,您可以查看官方documentation

修改

如果要在内存中应用解析日期和分组操作,可以像这样重构代码;

db.JobProgress.Where(x => Job_Ids.Contains(x.JobId))
.Select(x => new {DateStr = x.Job.Date,Total = x.total}).ToList()
.GroupBy(x => new{ Year = Year_from_strDate(DateStr), Month = Month_From_strDate(DateStr)})
.Select(ln => new MyViewModel
{
   Year = ln.Key.Year,
   Month = ln.Key.Month,
   Amount = ln.Sum(r => r.Total)
}).ToList();

另外,我不知道Year_from_strDateMonth_From_strDate方法是什么,但我假设您可以使用这些方法成功解析日期时间。