用于创建Where查询的LINQ扩展方法



我正在尝试创建一个扩展方法,该方法可用于LINQ to Object和LINQ to Entities,以创建一个正常运行的Where查询。最终会有更多的内容涉及其中,但首先我遇到了一个问题,即如何让方法接受lambda列选择并将其用作Contains()调用的基础。我已经能够为LINQ to Objects做一些工作,但当我试图将其用于LINQ to Entity时,它出现了问题。

以下是适用于LINQ to Objects的内容:

public static IQueryable<T> WhereContains<T>(this IQueryable<T> query, Expression<Func<T, string>> column, IList<string> values)
{
return query.Where(o => values.Contains(column.Compile().Invoke(o)));
}

如果这是针对实体框架运行的,我会得到一个异常,说明

LINQ to Entities无法识别该方法。。。

我有一种感觉,这需要使用ExpressionVisitor,但我还不知道它需要如何连接。有人能做到这一点吗?

更新:

我认为这不是重复的,因为xanatos提供的答案显示了在不使用ExpressionVisitor的情况下实现这一目标的直接方法。

是的,您必须稍微修改Expression,但不需要ExpressionVisitor。它要简单得多。

public static IQueryable<TSource> WhereContains<TSource, TResult>(this IQueryable<TSource> query, Expression<Func<TSource, TResult>> column, IList<TResult> values)
{
MethodInfo iListTResultContains = typeof(ICollection<>).MakeGenericType(typeof(TResult)).GetMethod("Contains", BindingFlags.Instance | BindingFlags.Public, null, new[] { typeof(TResult) }, null);
var contains = Expression.Call(Expression.Constant(values), iListTResultContains, column.Body);
var lambda = Expression.Lambda<Func<TSource, bool>>(contains, column.Parameters);
return query.Where(lambda);
}

请注意,我对它进行了一点扩展,以涵盖string以外的内容。

最新更新