如何检测IQueryable<T>
是否应用了where
过滤器?
在此代码中,我需要以编程方式了解queryFiltered
已应用where
并且query
不
IQueryable<Customer> query = Context.Customers;
IQueryable<Customer> queryFiltered = Context.Customers
.Where(c=>c.Name.Contains("ABC"));
答案 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 FS
将WereFinder.VisitMethodCall
更改为
if
答案 2 :(得分:1)
最简单的方法是致电q.Expression.ToString().Contains(".Where(")
。如您所见,query.Expression.ToString().Contains(".Where(")
返回false而queryFiltered.Expression.ToString().Contains(".Where(")
返回true。
如果将其他表达式视为“过滤”,则可能需要更多的复杂性,但对于表达式访问者方法也是如此。
我会给你一些相当骇人听闻的东西,但看起来确实简单得多。