检测应用于IQueryable <T>的位置

Rod*_*rez 6 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"));
Run Code Online (Sandbox Code Playgroud)

cas*_*One 9

您将必须解析在实现上ExpressionExpression属性返回的内容IQueryable<T>.

在爬网时,您将不得不查询被调用的Queryable.Where方法Expression.

另请注意,虽然Queryable.Where这将是检测where过滤器的最常用方法,但查询语法允许使用其他实现(取决于using指令中使用的命名空间); 如果你有一些没有使用Queryable.Where扩展方法的东西,那么你必须明确地寻找它(或者使用更通用的过滤Where方法来获取IQueryable<T>并返回一个方法IQueryable<T>).

ExpressionVisitor(如由萨那托斯指出的)提供了爬行的一个非常简单的方法Expression树,我强烈建议使用这种方法为处理您的基本Expression树.

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


xan*_*tos 5

如果您使用的是 C# 4.0,则可以使用以下示例代码:使用 ExpressionVisitor 获取所有“where”调用

它基于ExpressionVisitor. 它“访问” a 的各个元素IQueryable<T>以找到Where零件。看起来很简单。

如果您使用的是 C# = 3.5,则可以使用ExpressionVisitorMSDN 的“如何:实现表达式树访问者”中的示例以及WhereFinder上一个链接中的示例(它们可以正常工作,刚刚经过测试)

使用代码:

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

if (wheres.Any())
{
    // There are Where in the query!
}
Run Code Online (Sandbox Code Playgroud)

如果您(正确地)与Rune FS, 一样偏执WereFinder.VisitMethodCall,请将 更改if

if (expression.Method.Name == "Where" && expression.Method.DeclaringType.FullName == "System.Linq.Queryable")
Run Code Online (Sandbox Code Playgroud)