在没有 PredicateBuilder 的情况下将谓词动态添加到表达式
Posted
技术标签:
【中文标题】在没有 PredicateBuilder 的情况下将谓词动态添加到表达式【英文标题】:Add dynamically predicate to expression without PredicateBuilder 【发布时间】:2019-04-14 09:26:32 【问题描述】:我使用linqToEntities
并想动态添加OR
条件。
我知道there is a great library PredicateBuilder
by brother Albahari 可以解决我的任务,但我不能使用它。
我的情况如下:
IEnumerable<Condition> conditions = new List<Condition>()
new Condition()IdReference = 1, TableName = "Table1" ,
new Condition()IdReference = 2, TableName = "Table2" ,
new Condition()IdReference = 3, TableName = "Table3" ,
// and so on
;
我拥有的是:
var histories = db.History as IQueryable<History>;
foreach (var cond in conditions)
//What code should be here to be translated into:
/*
histories = histories
.Where(h => h.IdReference == 1 && h.TableName =="Table1"
|| h.IdReference == 2 && h.TableName == "Table2"
|| h.IdReference == 3 && h.TableName == "Table3");
// and so on
*/
但是,我事先不知道conditions
会有多少。
如何从IEnumerable<Condition>
动态添加OR
条件?
【问题讨论】:
如果您没有太多组合,只需使用一些条件:if(thisIsTheCase) histories = histories.Where(// put your conditions else if(another Case) histories = histories.Where(// put your conditions
add more if else,直到您涵盖所有情况。您也可以通过创建动态表达式来做到这一点,但这并不容易,因为您需要组合表达式。
为什么不能使用PredicateBuilder
?
@CodingYoshi 因为我的代码不会通过代码审查。
【参考方案1】:
不确定使用谓词构建器有什么问题 - 它不一定是 LINQ Kit 包,所谓的谓词构建器通常是具有 2 个扩展方法的单个静态类 - 例如 Universal Predicate Builder 或我自己的 PredicateUtils
来自Establish a link between two lists in linq to entities where clause 和类似的。
无论如何,一旦你想要它,当然可以只使用普通的Expression 类静态方法来构建它。
添加以下内容以消除在每次调用之前编写Expression.
的需要:
using static System.Linq.Expressions.Expression;
然后使用这样的东西:
if (conditions.Any())
var parameter = Parameter(typeof(History));
var body = conditions
.Select(condition => Expression.Constant(condition))
.Select(condition => Expression.AndAlso(
Expression.Equal(
Expression.PropertyOrField(parameter, nameof(History.IdReference)),
Expression.Convert(
Expression.PropertyOrField(condition, nameof(Condition.IdReference))
, Expression.PropertyOrField(parameter, nameof(History.IdReference)).Type)
),
Expression.Equal(
Expression.PropertyOrField(parameter, nameof(History.TableName)),
Expression.Convert(
Expression.PropertyOrField(condition, nameof(Condition.TableName))
, Expression.PropertyOrField(parameter, nameof(History.TableName)).Type)
)
))
.Aggregate(Expression.OrElse);
var predicate = Lambda<Func<History, bool>>(body, parameter);
histories = histories.Where(predicate);
【讨论】:
【参考方案2】:我理解你的意思
var histories = db.History as IQueryable<History>;
foreach (var cond in conditions)
//What code should be here to be translated into:
histories = histories
.Where(h => h.IdReference == cond.IdReference &&
h.TableName ==cond.TableName );
【讨论】:
他直到运行时才知道条件。如果他们知道,这将起作用。 据我了解,他不知道历史列表中有多少条件,但他在条件列表中有固定条件,因此在条件列表中循环并比较!正如我所想:) 链接Where
s 是and
而不是or
。以上是关于在没有 PredicateBuilder 的情况下将谓词动态添加到表达式的主要内容,如果未能解决你的问题,请参考以下文章
将 LinqKit PredicateBuilder 用于相关模型(EF Core)
Entity Framework 4.1 Code First - 使用 LinqKit PredicateBuilder 时忽略包含
如何使用 PredicateBuilder、EF Core 5 和 Postgresql 10+ 执行不区分大小写和重音的 LIKE(子字符串)查询?