2

我需要构建一个“介于”函数来检查日期是否包含在 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

4 回答 4

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));
于 2012-09-19T14:11:06.237 回答
1

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

var now = DateTime.Now;    
var expiredEntities = entities.Repositories.Where(repository => repository.ExpiryDate < now).ToList();
于 2012-09-19T14:06:41.977 回答
0

现在,如果我遵循这个正确的话,你真的很想写:

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

但是,您不能,因为DateLINQ to 实体不支持 DateTime 的属性。

同样,你不能写:

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
于 2017-10-04T21:24:15.950 回答
-1

为什么要打扰所有这些魔法?为什么不这样做呢?

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

}
于 2012-09-19T13:44:18.663 回答