检测应用于IQueryable <t> </t>的位置

时间:2011-10-26 12:43:17

标签: c# linq entity-framework

如何检测IQueryable<T>是否应用了where过滤器?

在此代码中,我需要以编程方式了解queryFiltered已应用where并且query

IQueryable<Customer> query = Context.Customers;
IQueryable<Customer> queryFiltered = Context.Customers
                                            .Where(c=>c.Name.Contains("ABC"));

3 个答案:

答案 0 :(得分:9)

您必须解析Expression实施中Expression property返回的IQueryable<T>

在抓取Expression树时,您必须查询被调用的Queryable.Where method

另请注意,虽然Queryable.Where将是检测where过滤器的最常用方法,但查询语法允许使用其他实现(取决于{{中使用的命名空间) 3}});如果您的某些内容未使用Queryable.Where扩展方法,那么您必须明确地查找(或使用更通用的方法过滤Where方法,该方法需要IQueryable<T> }并返回IQueryable<T>)。

using directives(作为ExpressionVisitor class)提供了一种非常简单的方法来抓取Expression树,我强烈建议您使用该方法作为处理Expression树的基础

值得注意的是,在类级别上存储和公开状态需要ExpressionVisitor类实现。因此,最好(IMO)创建一次性执行操作的内部类,然后使用公共方法每次创建ExpressionVisitor的新实例;这将有助于处理变异状态,如果正确完成,将允许该方法也是线程安全的(如果这是您的关注)。

答案 1 :(得分:3)

如果您使用的是C#4.0,则可以使用以下示例代码:Get all 'where' calls using ExpressionVisitor

它基于ExpressionVisitor。它“访问”IQueryable<T>的各个元素以查找Where部分。这看起来很简单。

如果您使用的是C#= 3.5,则可以使用MSDN的ExpressionVisitor样本How to: Implement an Expression Tree Visitor加上前一个链接中的WhereFinder(它们一起正常工作,只是经过测试)

使用代码:

var wf = new WhereFinder();
var wheres = wf.GetWhere(query.Expression);

if (wheres.Any())
{
    // There are Where in the query!
}

如果您(正确)与[{1}}一样偏执,则Rune FSWereFinder.VisitMethodCall更改为

if

答案 2 :(得分:1)

最简单的方法是致电q.Expression.ToString().Contains(".Where(")。如您所见,query.Expression.ToString().Contains(".Where(")返回false而queryFiltered.Expression.ToString().Contains(".Where(")返回true。

如果将其他表达式视为“过滤”,则可能需要更多的复杂性,但对于表达式访问者方法也是如此。

我会给你一些相当骇人听闻的东西,但看起来确实简单得多。