检测应用于 IQueryable 的位置
本文关键字:位置 应用于 IQueryable 检测 | 更新日期: 2023-09-27 18:12:21
如何检测IQueryable<T>
是否应用了where
过滤器?
在此代码中,我需要以编程方式知道queryFiltered
应用了where
,而query
没有
IQueryable<Customer> query = Context.Customers;
IQueryable<Customer> queryFiltered = Context.Customers
.Where(c=>c.Name.Contains("ABC"));
您必须分析从IQueryable<T>
实现上的 Expression
属性返回的Expression
。
您必须查询在对Expression
树进行爬网时调用的Queryable.Where
方法。
另请注意,虽然Queryable.Where
将是检测where
过滤器的最常见方法,但查询语法允许使用其他实现(取决于 using
指令中使用的命名空间(;如果您有不使用 Queryable.Where
扩展方法的内容,则必须显式查找它(或使用更通用的过滤方法Where
方法取IQueryable<T>
并返回IQueryable<T>
(。
ExpressionVisitor
类(如xanatos指出的那样(提供了一种非常简单的爬行Expression
树的方法,我强烈建议使用该方法作为处理Expression
树的基础。
值得注意的是,ExpressionVisitor
类实现都需要在类级别存储和公开状态。 因此,最好(IMO(创建一次性执行操作的内部类,然后使用一个公共方法,每次都创建一个ExpressionVisitor
的新实例;这将有助于处理突变状态,如果操作正确,也将允许该方法是线程安全的(如果这是您的问题(。
如果您使用的是 C# 4.0,则可以使用以下示例代码: 使用 ExpressionVisitor 获取所有"where"调用
它基于ExpressionVisitor
.它"访问"IQueryable<T>
的各种元素以查找Where
零件。这似乎很简单。
如果您使用的是 C# = 3.5,则可以使用 MSDN 的如何:实现表达式树访问者中的ExpressionVisitor
示例以及上一个链接中的WhereFinder
(它们可以正常工作,刚刚测试(
要使用代码:
var wf = new WhereFinder();
var wheres = wf.GetWhere(query.Expression);
if (wheres.Any())
{
// There are Where in the query!
}
如果您(正确(像Rune FS
一样偏执,则WereFinder.VisitMethodCall
,将if
更改为
if (expression.Method.Name == "Where" && expression.Method.DeclaringType.FullName == "System.Linq.Queryable")
最简单的方法是调用q.Expression.ToString().Contains(".Where(")
。如您所见,query.Expression.ToString().Contains(".Where(")
返回 false,而 queryFiltered.Expression.ToString().Contains(".Where(")
返回 true。
如果将其他表达式计为"筛选",则可能需要比这更复杂的情况,但表达式访问者方法也是如此。
我会给你一些相当笨拙的东西,但它看起来确实简单得多。