在运行时按 Day/Week/Month/Year 动态分组
Dynamically grouping by Day/Week/Month/Year at Runtime
我想根据传递到函数中的 int 对查询进行不同的分组。目前我有这个非常 hacky 的解决方案:
`.GroupBy(occurrence => new { date =
// Bucket by day.
timeBucket == 0 ? DbFunctions.TruncateTime(occurrence.occurrenceDate) :
// Bucket by week.
timeBucket == 1 ? DbFunctions.AddDays(DbFunctions.CreateDateTime(occurrence.occurrenceDate.Year, 1, 1, 0, 0, 0), 7*(occurrence.occurrenceDate.DayOfYear/7)) :
// Bucket by month.
timeBucket == 2 ? DbFunctions.TruncateTime(DbFunctions.CreateDateTime(occurrence.occurrenceDate.Year, occurrence.occurrenceDate.Month, 1, 1, 1, 1)) :
// Bucket by year.
DbFunctions.TruncateTime(DbFunctions.CreateDateTime(occurrence.occurrenceDate.Year, 1, 1, 1, 1, 1)),
type = occurrence.type })`
我如何计算日期的细节对我来说不是太重要(但无论如何请随时提供帮助)。我想避免为数据库中的每一行都检查这个 case 语句。无论如何要避免这样做吗?我已经尝试了多种解决方案,例如使用表达式,但我无法 return 我想要的对象,因为表达式树必须是无参数的...
如果有人有解决方案,将不胜感激。
谢谢!
为什么不做这样的事情(主要是伪代码):
switch(timeBucket)
{
case 0: result=query.GroupBy(...);
case 1: result=query.GroupBy(...);
case 2: result=query.GroupBy(...);
}
按日期、月份、年份分组很容易。周因您的日历周而异。
List<DateTime> occurance = new List<DateTime>();
var dayGroup = occurance.GroupBy(x => x.Date);
var yearGroup = occurance.GroupBy(x => x.Year);
var monthGroup = occurance.GroupBy(x => newKeyValuePair<int,int>(x.Month, x.Year));
定义石斑鱼class:
class TimeGrouper
{
public int Year { get; set; }
public int Month { get; set; }
public int Week { get; set; }
public int Day { get; set; }
}
和 return 表达式的函数:
using System.Data.Entity.SqlServer;
...
Expression<Func<Occurrence, TimeGrouper>> GetGrouper(int grouping)
{
switch (grouping)
{
case 1:
return o => new TimeGrouper
{
Year = o.occurrenceDate.Year
};
case 2:
return o => new TimeGrouper
{
Year = o.occurrenceDate.Year,
Month = o.occurrenceDate.Month
};
case 3:
return o => new TimeGrouper
{
Year = o.occurrenceDate.Year,
Week = SqlFunctions.DatePart("wk", o.StartDate).Value
};
default:
return o => new TimeGrouper
{
Year = o.occurrenceDate.Year,
Day = SqlFunctions.DatePart("dy", o.StartDate).Value
};
}
}
现在可以打电话了
db.Occurrences.GroupBy(GetGrouper(3));
我想根据传递到函数中的 int 对查询进行不同的分组。目前我有这个非常 hacky 的解决方案:
`.GroupBy(occurrence => new { date =
// Bucket by day.
timeBucket == 0 ? DbFunctions.TruncateTime(occurrence.occurrenceDate) :
// Bucket by week.
timeBucket == 1 ? DbFunctions.AddDays(DbFunctions.CreateDateTime(occurrence.occurrenceDate.Year, 1, 1, 0, 0, 0), 7*(occurrence.occurrenceDate.DayOfYear/7)) :
// Bucket by month.
timeBucket == 2 ? DbFunctions.TruncateTime(DbFunctions.CreateDateTime(occurrence.occurrenceDate.Year, occurrence.occurrenceDate.Month, 1, 1, 1, 1)) :
// Bucket by year.
DbFunctions.TruncateTime(DbFunctions.CreateDateTime(occurrence.occurrenceDate.Year, 1, 1, 1, 1, 1)),
type = occurrence.type })`
我如何计算日期的细节对我来说不是太重要(但无论如何请随时提供帮助)。我想避免为数据库中的每一行都检查这个 case 语句。无论如何要避免这样做吗?我已经尝试了多种解决方案,例如使用表达式,但我无法 return 我想要的对象,因为表达式树必须是无参数的...
如果有人有解决方案,将不胜感激。
谢谢!
为什么不做这样的事情(主要是伪代码):
switch(timeBucket)
{
case 0: result=query.GroupBy(...);
case 1: result=query.GroupBy(...);
case 2: result=query.GroupBy(...);
}
按日期、月份、年份分组很容易。周因您的日历周而异。
List<DateTime> occurance = new List<DateTime>();
var dayGroup = occurance.GroupBy(x => x.Date);
var yearGroup = occurance.GroupBy(x => x.Year);
var monthGroup = occurance.GroupBy(x => newKeyValuePair<int,int>(x.Month, x.Year));
定义石斑鱼class:
class TimeGrouper
{
public int Year { get; set; }
public int Month { get; set; }
public int Week { get; set; }
public int Day { get; set; }
}
和 return 表达式的函数:
using System.Data.Entity.SqlServer;
...
Expression<Func<Occurrence, TimeGrouper>> GetGrouper(int grouping)
{
switch (grouping)
{
case 1:
return o => new TimeGrouper
{
Year = o.occurrenceDate.Year
};
case 2:
return o => new TimeGrouper
{
Year = o.occurrenceDate.Year,
Month = o.occurrenceDate.Month
};
case 3:
return o => new TimeGrouper
{
Year = o.occurrenceDate.Year,
Week = SqlFunctions.DatePart("wk", o.StartDate).Value
};
default:
return o => new TimeGrouper
{
Year = o.occurrenceDate.Year,
Day = SqlFunctions.DatePart("dy", o.StartDate).Value
};
}
}
现在可以打电话了
db.Occurrences.GroupBy(GetGrouper(3));