表达式树,用于了解日期是否在c#中的2个日期之间

时间:2012-09-19 13:42:44

标签: c# .net linq expression func

我需要构建一个“between”函数来检查日期是否包含在2个日期的范围内。我写了这个,但它不起作用:

private static Expression<Func<TElement, bool>> IsDateBetween<TElement>(Expression<Func<TElement, object>> valueSelector, DateTime date)
{
    var p = valueSelector.Parameters.Single();

    var after = Expression.LessThanOrEqual(
        Expression.Property(valueSelector.Body, "FromDate"), Expression.Constant(date.Date, typeof(DateTime)));

    var before = Expression.GreaterThanOrEqual(
        Expression.Property(valueSelector.Body, "ToDate"), Expression.Constant(date.Date, typeof(DateTime)));

    Expression body = Expression.And(after, before);

    return Expression.Lambda<Func<TElement, bool>>(body, p);
}

我这样称呼它:

DataContext.EventHistories.Where(IsDateBetween<EventHistory>(h => new { h.FromDate, h.ToDate }, dateInTheMiddle))

我必须使用这种方式,因为linq实体不支持日期。

由于

4 个答案:

答案 0 :(得分:3)

你可以尝试类似的东西

public static IQueryable<TElement> IsDateBetween<TElement>(this IQueryable<TElement> queryable, 
                                                           Expression<Func<TElement, DateTime>> fromDate, 
                                                           Expression<Func<TElement, DateTime>> toDate, 
                                                           DateTime date)
{
    var p = fromDate.Parameters.Single();
    Expression member = p;

    Expression fromExpression = Expression.Property(member, (fromDate.Body as MemberExpression).Member.Name);
    Expression toExpression = Expression.Property(member, (toDate.Body as MemberExpression).Member.Name);

    var after = Expression.LessThanOrEqual(fromExpression,
         Expression.Constant(date, typeof(DateTime)));

    var before = Expression.GreaterThanOrEqual(
        toExpression, Expression.Constant(date, typeof(DateTime)));

    Expression body = Expression.And(after, before);

    var predicate = Expression.Lambda<Func<TElement, bool>>(body, p);
    return queryable.Where(predicate);
}

使用

DataContext.EventHistories.WhereDateBetween(h =>  h.FromDate, h => h.ToDate, dateInTheMiddle));

但做起来很复杂

var myDate = DateTime.Now();

var result = DataContext.EventHistories.Where(m => m.FromDate >= myDate && m.ToDate<=myDate );

修改

好吧,要模拟DateTime.Date,你可以这样做:

var myDate = DateTime.Now.Date();
var res = histories.AsQueryable()
.Where(m => 
EntityFunctions.CreateDateTime(m.FromDate.Year, m.FromDate.Month, m.FromDate.Day, 0, 0, 0) >= DateTime.Now && 
EntityFunctions.CreateDateTime(m.ToDate.Year, m.ToDate.Month, m.ToDate.Day, 0, 0, 0) <= DateTime.Now)

或创建界面

public interface IFromDateToDate
{
    DateTime FromDate { get; set; }
    DateTime ToDate { get; set; }
}

和扩展方法

public static IQueryable<T> WhereDatesBetween<T>(this IQueryable<T> queryable, DateTime myDate) where T : IFromDateToDate
{
    myDate = myDate.Date;
    return queryable.Where(m =>
                           EntityFunctions.CreateDateTime(m.FromDate.Year, m.FromDate.Month, m.FromDate.Day, 0, 0, 0) >= myDate &&
                           EntityFunctions.CreateDateTime(m.FromDate.Year, m.FromDate.Month, m.FromDate.Day, 0, 0, 0) <= myDate);
}

用法:

DataContext.EventHistories.WhereDatesBetween(dateInTheMiddle));

答案 1 :(得分:1)

LinQ to Entities DOES支持DateTime - 我在项目中使用它并且没有问题:

var now = DateTime.Now;    
var expiredEntities = entities.Repositories.Where(repository => repository.ExpiryDate < now).ToList();

答案 2 :(得分:0)

现在,如果我遵循这一点,你真的想写:

from item in MyTable
where FromDate <= Item.Somedate.Date 
   && Item.Somedate.Date <= ToDate
select item

但是,你不能,因为LINQ to实体不支持DateTime的Date属性。

同样,你不能写:

from item in MyTable
where FromDate <= Item.SomeDate 
   && Item.SomeDate <= ToDate
select item

因为,我认为,ToDate设置为午夜,如果Item.SomeDate有时间,则会在ToDate之后,即使它在ToDate上。

如果是这种情况,那么通常的做法就是将上限设为独占值(即首先)部分内容)。因此:

  toDate = toDate.Date.AddDay(1);

from item in MyTable
where FromDate <= Item.SomeDate 
   && Item.SomeDate < ToDate
select item

答案 3 :(得分:-1)

为什么要烦恼所有的魔力?为什么不这样做?

if (date >= startDate and date <= endDate) {

}