检测应用于 IQueryable的位置
如何检测 IQueryable
是否应用了 where
过滤器?
在此代码中,我需要以编程方式知道 queryFiltered
已应用 where
而 query
没有
IQueryable<Customer> query = Context.Customers;
IQueryable<Customer> queryFiltered = Context.Customers
.Where(c=>c.Name.Contains("ABC"));
How can I detect if a IQueryable<T>
has a where
filter applied?
In this code, I need to know programmatically that queryFiltered
has a where
applied to it and query
doesn't
IQueryable<Customer> query = Context.Customers;
IQueryable<Customer> queryFiltered = Context.Customers
.Where(c=>c.Name.Contains("ABC"));
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
如果您使用的是 C# 4.0,则可以使用以下示例代码: 获取所有 ' where' 使用 ExpressionVisitor 进行调用
它基于
ExpressionVisitor
。它“访问”IQueryable
的各个元素以查找Where
部分。看起来很简单。如果您使用的是 C# = 3.5,则可以使用 MSDN 如何:实现表达式树访问者 加上上一个链接中的
WhereFinder
(它们可以工作正确地在一起,刚刚测试)要使用代码:
如果您(正确地)像
Rune FS
一样偏执,则对于WereFinder.VisitMethodCall
,请更改if至
If you are using C# 4.0 you can use this sample code: Get all 'where' calls using ExpressionVisitor
It's based on
ExpressionVisitor
. It "visits" the various elements of aIQueryable<T>
to find theWhere
parts. It seems simple enough.If you are on C# = 3.5, you can use the
ExpressionVisitor
sample from MSDN's How to: Implement an Expression Tree Visitor PLUS theWhereFinder
from the previous link (they work correctly together, just tested)To use the code:
If you are (correctly) as much paranoid as
Rune FS
, to theWereFinder.VisitMethodCall
, change theif
to最简单的方法是调用 q.Expression.ToString().Contains(".Where(")。如您所见,
query.Expression.ToString().Contains(".Where (")
返回 false,而queryFiltered.Expression.ToString().Contains(".Where(")
返回 true。如果将其他表达式算作 ",则可能需要比这更复杂的值过滤”,但是表达式访问者方法也是如此。
我承认这有些古怪,但它看起来确实简单得多。
The simplest way is call
q.Expression.ToString().Contains(".Where(")
. As you can see,query.Expression.ToString().Contains(".Where(")
returns false whilequeryFiltered.Expression.ToString().Contains(".Where(")
returns true.You may need more complexity than that if you count other expressions as "filtering", but that is true with the expression visitor approach too.
There's something rather hacky about this I'll grant you, but it does seem much simpler.
您必须解析
表达式
从 上的
表达式
属性IQueryable
实现。您必须查询
Queryable当您爬取
方法。Expression
树时调用Where另请注意,虽然
Queryable.Where
将是检测where
过滤器的最常见方法,但查询语法允许使用其他实现(取决于名称空间)用于using
指令);如果您有一些未使用Queryable.Where
扩展方法的内容,那么您必须显式查找该扩展方法(或使用更通用的过滤Where
方法接受IQueryable
并返回IQueryable
的方法)。ExpressionVisitor
类(如xanatos 指出)提供了一种非常简单的方法来抓取表达式
树,我强烈建议使用该方法作为处理表达式
树的基础。值得注意的是,
ExpressionVisitor
类实现需要在类级别存储和公开状态。因此,最好(IMO)创建一次性执行操作的内部类,然后使用一个公共方法来每次创建一个新的ExpressionVisitor
实例;这将有助于处理变异状态,如果做得正确,也将允许该方法是线程安全的(如果这是您关心的问题)。You will have to parse the
Expression
that is returned from theExpression
property on theIQueryable<T>
implementation.You'll have to query for the
Queryable.Where
method being called as you crawl theExpression
tree.Also note that while
Queryable.Where
is going to be the most common way to detect awhere
filter, query syntax allows for other implementations to be used (depending on what namespaces are used in theusing
directives); if you have something that is not using theQueryable.Where
extension method then you'll have to look for that explicitly (or use a more generic method of filtering for aWhere
method that takes anIQueryable<T>
and returns anIQueryable<T>
).The
ExpressionVisitor
class (as pointed out by xanatos) provides a very easy way of crawling theExpression
tree, I highly recommend using that approach as a base for processing yourExpression
tree.Of note is that
ExpressionVisitor
class implementations are required to store and expose state on the class level. Because of that, it would be best (IMO) to create internal classes that perform the action one-time and then have a public method which creates a new instance of theExpressionVisitor
every time; this will help with dealing with mutating state, and if done properly, will allow the method to be thread-safe as well (if that is a concern of yours).