从表达式树中删除一个条件

本文关键字:一个 条件 表达式 删除 | 更新日期: 2023-09-27 17:49:55

我使用实体框架来处理MVC应用程序中的数据库:我使用start表单中的几个字段为应用程序创建了一个搜索引擎,并设置了来自用户角色的特权,因此创建select语句的例程正在增长,所以有时我会遇到这种情况。在创建选区之前:

  1. var orders = db.Orders。其中(ord =>

    在源代码中的

    后面,在某些情况下,用户类型,过滤器组合等,我必须更改此过滤器或删除此条件

  2. orders = db.Orders。其中(ord =>

    这是一个简单的例子,因为这样做我宽松的另一个过滤器在Linq表达式树,并导致我经常请求添加特性,很难重组之前测试所有先决条件的所有代码添加条件表达式树,所以我想知道是否可以删除语句添加后的Linq表达式树和树解析和转换前的sql查询

卢卡

从表达式树中删除一个条件

假设我正确地理解了你的问题,我认为最简单的方法是推迟查询的创建,直到你收集了所有需要知道查询应该是什么样子的数据,即在这种情况下,这意味着你只在你已经知道是否实际需要应用条件之后才构建查询。

如果你不可能推迟查询的创建(在我看来这就是你所说的),但你仍然可以预测哪些条件可能需要在稍后的点被删除,我会考虑在查询中引入一个布尔哨兵,例如基于你的查询片段:

var orders = db.Orders.Where( ord => 
    (isFirstConditionRelevant && ord.Channel == 1) 
    || (isSecondConditionRelvant && ord.Channel == 2));

变量'isFirstConditionRelevant'和'isSecondConditionRelevant'最初将被设置为true,并将被查询表达式捕获,但如果您需要相应的条件没有效果,您可以在稍后的点(例如,在执行查询之前)设置为false。注意,使用这种方法,查询的SQL转换仍将包含条件,但它还将包含每个哨兵的参数,该参数将在服务器执行查询时短路布尔逻辑。

还要注意条件中的任何常量(例如' order . channel == 1'中的'1')将在SQL中被转换为常量。我建议使用变量,因为这会在SQL查询中引入参数,从而增加查询计划在服务器上被重用的机会。

另一种有用的方法是利用对查询中表达式变量引用的支持,例如,您可以将类型为expression>的变量传递给Where子句,并在稍后将变量的值替换为正确的谓词。如果我没记错的话,LINQ to Entities支持在嵌套集合上使用表达式变量作为谓词条件,方法是在查询中对集合应用AsQueryable操作符。否则,您可以利用LINQ工具包提供的对AsExpandable in的支持。你可以在LINQ Kit主页上找到更多的信息,以及使用表达式变量引用的例子:http://www.albahari.com/nutshell/linqkit.aspx。

我要考虑的第四种也是最复杂的方法是在执行查询之前使用我自己的访问器(例如,派生自System.Linq.Expressions.ExpressionVisitor)来重写LINQ表达式树(在这种情况下,从谓词中删除条件)。我没有一个表情访问者能做到这一点。相反,我可以提供一些指向解决问题不同部分的文章的指针:

  1. StackOverflow中的这个线程描述了如何使用表达式访问器来做一些查询重写:使用LINQ ExpressionVisitor来用lambda表达式中的属性引用替换原始参数。
  2. Alex James的这篇博文描述了如何编写一个拦截查询提供程序,它将在查询执行之前调用表达式重写访问者:http://blogs.msdn.com/b/alexj/archive/2010/03/01/tip-55-how-to-extend-an-iqueryable-by-wrapping-it.aspx.
  3. 下面的文章描述了一个可用于基于规则重写表达式的库:http://www.codeproject.com/Articles/24454/Modifying-LINQ-Expressions-with-Rewrite-Rules。

希望这对你有帮助!