Group by Weeks in LINQ to Entities
Solution 1:
You should be able to force the query to use LINQ to Objects rather than LINQ to Entities for the grouping, using a call to the AsEnumerable
extension method.
Try the following:
DateTime firstDay = GetFirstDayOfFirstWeekOfYear();
var userTimes =
from t in context.TrackedTimes.Where(myPredicateHere).AsEnumerable()
group t by new {t.User.UserName, WeekNumber = (t.TargetDate - firstDay).Days / 7} into ut
select new
{
UserName = ut.Key.UserName,
WeekNumber = ut.Key.WeekNumber,
Minutes = ut.Sum(t => t.Minutes)
};
This would at least mean that the where
clause gets executed by LINQ to Entities, but the group
clause, which is too complex for Entities to handle, gets done by LINQ to Objects.
Let me know if you have any luck with that.
Update
Here's another suggestion, which might allow you to use LINQ to Entities for the whole thing.
(t.TargetDate.Days - firstDay.Days) / 7
This simply expands the operation so that only integer subtraction is performed rather than DateTime
subtraction.
It is currently untested, so it may or may not work...
Solution 2:
You can use SQL functions also in the LINQ as long as you are using SQLServer:
using System.Data.Objects.SqlClient;
var codes = (from c in _twsEntities.PromoHistory
where (c.UserId == userId)
group c by SqlFunctions.DatePart("wk", c.DateAdded) into g
let MaxDate = g.Max(c => SqlFunctions.DatePart("wk",c.DateAdded))
let Count = g.Count()
orderby MaxDate
select new { g.Key, MaxDate, Count }).ToList();
This sample was adapted from MVP Zeeshan Hirani in this thread: a MSDN
Solution 3:
I had exactly this problem in my Time tracking application which needs to report tasks by week. I tried the arithmetic approach but failed to get anything reasonable working. I ended-up just adding a new column to the database with the week number in it and calculating this for each new row. Suddenly all the pain went away. I hated doing this as I am a great believer in DRY but I needed to make progress. Not the answer you want but another users point of view. I will be watching this for a decent answer.