Добавить динамический предикат в выражение без PredicateBuilder - PullRequest
0 голосов
/ 11 ноября 2018

Я использую linqToEntities и хотел бы добавить условие OR динамически.

Я знаю, что есть великая библиотека PredicateBuilder брата Албахари , и она может решить мою задачу, но я не могу ее использовать.

Мои условия выглядят так:

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. Как можно динамически добавлять условия OR из IEnumerable<Condition>?

Ответы [ 2 ]

0 голосов
/ 11 ноября 2018

Не уверен, в чем проблема с использованием построителя предикатов - это не обязательно должен быть пакет LINQ Kit, так называемый построитель предикатов обычно представляет собой один статический класс с двумя методами расширения - как Универсальный построитель предикатов или мой собственный PredicateUtils из Установить связь между двумя списками в linq для сущностей, в которых есть пункт и подобные.

В любом случае, если вы захотите, конечно, его можно построить с помощью простых выражений статических методов класса.

Добавьте следующее, чтобы избежать необходимости писать 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);
}
0 голосов
/ 11 ноября 2018

Как я понимаю, вы имеете в виду

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

}    
...