检测应用于 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> 的位置

您必须分析从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。

如果将其他表达式计为"筛选",则可能需要比这更复杂的情况,但表达式访问者方法也是如此。

我会给你一些相当笨拙的东西,但它看起来确实简单得多。