用IsInDateTimeRange扩展IQueryable

问题描述:

所以我厌倦了一遍又一遍重写相同的查询。用IsInDateTimeRange扩展IQueryable

repo.Query().Where(stuff => stuff.Timestamp >= minTime && stuff.Timestamp <= maxTime && ...); 

我想我应该有一个名为IsInDateTimeRange方法但是延长IQueryable,并使用它像这样

repo.Query().IsInDateTimeRange(stuff => stuff.Timestamp, minTime, maxTime) ... 

这将是IEnumerable非常方便,只需一个Func<T, DateTime>和两个DateTime S,为IQueryable我需要采取Expression,我不确定如何使用它。

这是我的尝试,但似乎没有工作。

public static IQueryable<TValue> IsInDateTimeRange<TValue>(
     this IQueryable<TValue> self, 
     Expression<Func<TValue, DateTime>> getMember, 
     DateTime minTime, 
     DateTime maxTime) 
    { 
     return self.Where(value => minTime >= getMember(value) && maxTime <= getMember(value)); 
    } 
+1

当你说没有工作,请解释这是什么意思。例外?编译错误? –

+1

由于'getMember(value)'噪声,大多数Linq提供者将无法将转换后的表达式转换为商店查询。您必须使用常规的'Expression.Property'访问器手动替换相关部分。 – haim770

+0

是的,编译器错误。由于它不是委托,因此无法调用getMember。 – jool

您可以通过手动构建基于传递给该方法的属性访问表达式表达式实现这一点:

public static IQueryable<TValue> IsInDateTimeRange<TValue>(
    this IQueryable<TValue> self, 
    Expression<Func<TValue, DateTime>> getMember, 
    DateTime minTime, 
    DateTime maxTime) 
{ 
    var getMemberBody = getMember.Body; 
    var filter = Expression.Lambda<Func<TValue, bool>>(
     Expression.And(
      Expression.LessThanOrEqual(
       Expression.Constant(minTime), 
       getMemberBody 
      ), 
      Expression.LessThanOrEqual(
       getMemberBody, 
       Expression.Constant(maxTime) 
      ) 
     ), 
     getMember.Parameters 
    ); 
    return self.Where(filter); 
} 
+0

打败我吧。只是我可能做的调整就是你实际上不需要使用getMember.Parameters.First()。您应该能够将'getMembers.Parameters'作为第二个参数传递给'Lambda ()'。另外,第一个'LessThanOrEqual'应该是'GreaterThanOrEqual' :)。 –

+0

@MikeStrobel你是对的,编辑使它如此:) –

+0

修复你的小逻辑错误(你使用了两次'