【问题标题】:Add dynamically predicate to expression without PredicateBuilder在没有 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&lt;Condition&gt; 动态添加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 因为我的代码不会通过代码审查。

标签: c# entity-framework linq entity-framework-6 linq-to-entities


【解决方案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 );
    
    }    
    

    【讨论】:

    • 他直到运行时才知道条件。如果他们知道,这将起作用。
    • 据我了解,他不知道历史列表中有多少条件,但他在条件列表中有固定条件,因此在条件列表中循环并比较!正如我所想:)
    • 链接Wheres 是and 而不是or
    猜你喜欢
    • 1970-01-01
    • 2014-04-06
    • 2014-08-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多