我有一个可查询对象,在其中使用了各种Where
和WhereBetween
语句来将集合缩小到一定范围。现在我需要添加一种Where || WhereBetween
。换句话说,我不能像以前那样将它们链接在一起,因为这将作为一个And运算。那么,我该怎么做?
我看到两种可能性:
- 从现有的Queryable创建两个Queryable,一个使用
Where
,另一个使用WhereBetween
。然后将它们连接起来。不知道是否可能?而且,虽然不是在我特定的情况下,你很可能最终会得到重复的数据... - 以某种方式将
Where
表达式和在WhereBetween
中创建的表达式合并,使用Or等逻辑符号。
首先提到的第一种可能性,我不确定是否可能。即使可能,我也不确定这是否是一个好方法。
第二种可能性,我认为是一种可选方案,但并不完全确定所有细节。下面是我另一个问题中的WhereBetween
方法,我现在使用它,它工作得很好:
public static IQueryable<TSource> WhereBetween<TSource, TValue>(
this IQueryable<TSource> source,
Expression<Func<TSource, TValue>> selector,
IEnumerable<Range<TValue>> ranges)
{
var param = Expression.Parameter(typeof(TSource), "x");
var member = Expression.Invoke(selector, param);
Expression body = null;
foreach (var range in ranges)
{
var filter = Expression.AndAlso(
Expression.GreaterThanOrEqual(member,
Expression.Constant(range.A, typeof(TValue))),
Expression.LessThanOrEqual(member,
Expression.Constant(range.B, typeof(TValue))));
body = body == null ? filter : Expression.OrElse(body, filter);
}
return body == null ? source : source.Where(
Expression.Lambda<Func<TSource, bool>>(body, param));
}
我在思考,也许可以将其表达式构建部分提取出来放到一个新的方法中,类似于这样:
public static IQueryable<TSource> WhereBetween<TSource, TValue>(
this IQueryable<TSource> source,
Expression<Func<TSource, TValue>> selector,
IEnumerable<Range<TValue>> ranges)
{
return source.Where(WhereBetween(selector, ranges));
}
public static Expression<Func<TSource, bool>> WhereBetween<TSource, TValue>(
Expression<Func<TSource, TValue>> selector,
IEnumerable<Range<TValue>> ranges)
{
var param = Expression.Parameter(typeof(TSource), "x");
var member = Expression.Invoke(selector, param);
Expression body = null;
foreach (var range in ranges)
{
var filter = Expression.AndAlso(
Expression.GreaterThanOrEqual(member,
Expression.Constant(range.A, typeof(TValue))),
Expression.LessThanOrEqual(member,
Expression.Constant(range.B, typeof(TValue))));
body = body == null ? filter : Expression.OrElse(body, filter);
}
return body == null
? ø => true
: Expression.Lambda<Func<TSource, bool>>(body, param);
}
我可以使用新方法来获取表达式,而不是查询。假设我有WhereBetween(ø => ø.Id, someRange)
和 ø => ø.SomeValue == null
,我应该如何将它们与Or组合起来呢?我查看了在WhereBetween
方法中使用的Expression.OrElse
,我认为这可能就是我需要的,或者也许是Expression.Or
。但是,我在处理表达式方面很不稳定,所以我不确定该选择什么,甚至不确定自己是否正确 :p
请问有人能给我一些指导吗?
UNION
还是在WHERE
子句中使用OR
更有效率? - Svish