IQueryable连接表达式

时间:2016-11-21 16:27:46

标签: c# entity-framework linq expression

假设我有一个Magazine类,其enum属性描述了订阅期(Monthly,Bimonthly,Quarterly,...)。因此,选择枚举中的值,可以使一些计算变得容易

使用实体框架我有DbContext DbSet<Magazine>

enum SubscriptionPeriodType
{
    Monthly = 1,
    Bimonthly = 2,
    Quarterly = 3,
    Annual = 12,
};
class Magazine
{
    public SubscriptionPeriodType SubscriptionPeriodType {get; set;}
    ...
}
public MyDbContext : DbContext
{
    public DbSet<Magazine> Magazines {get; set;}
    ...
}

鉴于一年内的日期,我想知道订阅期的第一天和最后一天。例如,如果我有季度订阅期,则为2016年5月15日,即2016年4月1日订阅期的第一天,最后一天为2016年6月30日。

计算如下(按照婴儿步骤)

Period CalculatePeriod(DateTime date) 
{
    SubscriptionPeriodType subscriptionPeriodType = dbContext.Magazines
        .Where(...)
        .Select(magazine => magazine.SubscriptionPeriodType;
    int periodLength = (int)subscriptionPeriodType;
    int periodNr = (date.Month - 1) / periodLength;
    // quarters are numbered 0..3

    int periodStartMonth = periodNr * periodLength + 1;
    // quarters start in months 1 / 4 / 7 / 10
    DateTime startPeriod = new DateTime(date.Year, periodStartMonth, 1);
    DateTime nextPeriod = startPeriod.AddMonths(periodLength);
    return new Period()
    {
        FirstDay = startPeriod,
        LastDay = nextPeriod.AddDays(-1),
    }

虽然此功能可以在IEnumerable.Select中使用,但却无法在IQueryable.Select中使用。您无法在IQueryable.Select中创建阻止声明。

但是,到达StartPeriodNextPeriod的计算非常简单。我想创建一个表达式树,我可以将其提供给我的Select语句。

到目前为止我做了什么 我知道如何将前几个语句创建为表达式:

Expression<Func<Magazine, SupbscriptionPeriodType>> e1 = 
     magazine => magazine.SubscriptionPeriodType;
Expression<Func<SubscriptionPeriodType, int>> PeriodLength = s => (int)s;
Expression<Func<DateTime, int, int>> PeriodNr = 
    (date, periodLength) => (date.Month - 1) / periodLength;

// etc.

但是如何将这些表达式连接成一个表达式以及如何在Select?

中调用它
var result = dbContext.Magazines
    .Where(...)
    .Select(magazine => ConcatenatedExpression.... )

0 个答案:

没有答案