通用IQueryable比较日期

时间:2015-04-27 14:44:48

标签: c# linq generics iqueryable

所以我试图在IQueryable中创建一个接收IQueryable和DateTime属性的函数,并返回一个与另一个日期时间进行比较的IQueryable。

目前,我必须针对几个不同的功能执行此操作,并且此代码可能会发生变化,因此我希望将其一般性地应用于IQueryable:

  FMGQueryableSet = FMGQueryableSet.Where(t => t.Created.Day >= StartDate.Value.Day)
                               .Where(t => t.Created.Month >= StartDate.Value.Month)
                               .Where(t => t.Created.Year >= StartDate.Value.Year);

相反,我希望能够做到这一点:

FMGQueryableSet = SetDateCompare(FMGQueryableSet, t=> t.Created, StartDate, false)

方法存根看起来像这样但是我无法弄清楚如何将传入的属性绑定到IQueryable

public IQueryable<T> SetDateCompare<T>(IQueryable<T> OriginalQuery, Expression<Func<DateTime>> QueryProperty, DateTime ComparisonDate, bool isGreaterThan = true) 
    where T : class
    {
        if(isGreaterThan)
        {
            OriginalQuery = OriginalQuery.Where(QueryProperty >= ComparisonDate.Day)
                            .Where(QueryProperty >= ComparisonDate.Month)
                            .Where(QueryProperty >= ComparisonDate.Year);
        }
        else
        {
            OriginalQuery = OriginalQuery.Where(QueryProperty <= ComparisonDate.Day)
                           .Where(QueryProperty <= ComparisonDate.Month)
                           .Where(QueryProperty <= ComparisonDate.Year);

        }
        return OriginalQuery;

    }

2 个答案:

答案 0 :(得分:1)

t =&gt; t.Created你想要的部分调用它的lambda表达式,表示从类型T获取DateTime的函数,所以你的参数应该是一个Func&lt; T,日期时间&GT;

考虑到这一点,你应该试试这个:

public IQueryable<T> SetDateCompare<T>(IQueryable<T> OriginalQuery, Func<T,DateTime> getDateFunc, DateTime ComparisonDate, bool isGreaterThan = true)
where T : class
{
    if (isGreaterThan)
    {
        OriginalQuery = OriginalQuery.Where(t => getDateFunc(t).Day >= ComparisonDate.Day)
                        .Where(t => getDateFunc(t).Month >= ComparisonDate.Month)
                        .Where(t => getDateFunc(t).Year >= ComparisonDate.Year);
    }
    else
    {
        OriginalQuery = OriginalQuery.Where(t => getDateFunc(t).Day <= ComparisonDate.Day)
                        .Where(t => getDateFunc(t).Month  <= ComparisonDate.Month)
                        .Where(t => getDateFunc(t).Year  <= ComparisonDate.Year);

    }
    return OriginalQuery;

}

答案 1 :(得分:1)

假设你真的想要你展示的不寻常的比较逻辑,这就是你如何做到的。如果您需要不同的比较逻辑,只需更改表达式ymdCompareLess和ymdCompareGreater。

要做的第一件事是创建一个可以传递给where子句的新表达式。您希望能够传入一个表达要比较的属性的表达式和一个用于比较的日期值。

我在下面创建了2个表达式,用于小于比较和大于比较。根据isGreaterThan传入的值,我们选择大于比较或小于比较的表达式。

我正在使用我在StackOverflow上第一次看到的替换访问者模式,通过将所有原始参数替换为其他表达式来创建新表达式。

一旦我们选择了要使用的表达式,我们就会替换该表达式的参数。第一个参数v1将替换为QueryProperty主体。假设您传递了SKPaymentTransaction之类的内容,那么该表达式的主体将为v => v.CreatedDate

第二个参数v2将替换为包含您传入的日期值的表达式常量。

结果将是创建的表达式看起来像CreatedDate,其中v => v.CreatedDate.Day >= (new DateTime(2005, 2, 3)).Day是您传入的表达式中的参数。

然后我们创建一个lambda表达式,将创建的表达式作为主体,并将参数作为参数传入。

最后,我们使用新的lambda表达式作为过滤器调用.Where方法并返回结果。

v