代码之家  ›  专栏  ›  技术社区  ›  StepUp

在不使用PredicateBuilder的情况下向表达式动态添加谓词

  •  2
  • StepUp  · 技术社区  · 6 年前

    我用 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>

    2 回复  |  直到 6 年前
        1
  •  2
  •   StepUp    6 年前

    不确定使用谓词生成器有什么问题-它不一定是LINQ Kit包,所谓的谓词生成器通常是一个带有两个扩展方法的单一静态类,如 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
  •  0
  •   Hitham Yosri    6 年前

    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 );
    
    }