Linq2SQL операторы "или / и" (условия ANDed / ORed) - PullRequest
2 голосов
/ 20 сентября 2009

Допустим, нам нужно применить несколько условий для выбора из таблицы под названием «Вещи» (неизвестный счет и природа)

если условия известны, мы можем написать

db.Things.Where(t=>foo1 && foo2 || foo3);

но если нам нужно построить условие «Где» программно, я могу представить, как мы можем применить условия «И»

IQuerable DesiredThings = db.Things.AsQuerable();
foreach (Condition c in AndedConditions)
DesiredThings = DesiredThings.Where(t => GenerateCondition(c,t));

А как насчет условий ORed? Примечание: мы не хотим выполнять объединение, уникальные или любые другие дорогостоящие операции, желательно, чтобы запрос генерировался так, как если бы мы написали его ad-hock

Заранее спасибо.


Дополнительно:

PredicateBuilder: Динамически составляемые предикаты выражений

Ответы [ 2 ]

5 голосов
/ 20 сентября 2009

Вы можете использовать класс Expression со статическими методами для выполнения во время выполнения.

Приведенный ниже код предназначен для создания делегата, принимающего один аргумент с именем value типа int , Он читается снизу вверх, поэтому такая строка звучит так:

var method = LambdaExpression.Lambda(orExp, Expression.Parameter(typeof(int), "value"));

тело метода сравнивает значение параметра с вызовом метода Bar вновь созданного объекта типа foo

var exp2 = Expression.Equal(Expression.Parameter(typeof(int), "value"), Expression.Property(Expression.New(typeof(Foo).GetConstructor(new Type[] { })), "Bar"));

Затем создается похожее выражение и / или их

        var orExp = Expression.OrElse(exp1, exp2);

Последняя вещь - это вызов для компиляции. Этот вызов генерирует делегат, который может использоваться в вашем вызове метода where.

надеюсь, это поможет мне на 100% не быть уверенным в выражении, чтобы получить значение из параметра

var exp1 = Expression.Equal(Expression.Parameter(typeof(int),"value"), Expression.Property(Expression.New(typeof(Bar).GetConstructor(new Type[] { })), "Foo"));
            var exp2 = Expression.Equal(Expression.Parameter(typeof(int), "value"), Expression.Property(Expression.New(typeof(Foo).GetConstructor(new Type[] { })), "Bar"));
            var orExp = Expression.OrElse(exp1, exp2);
            var method = LambdaExpression.Lambda(orExp, Expression.Parameter(typeof(int), "value"));
            method.Compile();

Возможно, вы захотите посмотреть вызов для вызова вместо компиляции выражения, если вам нужно, чтобы выражение LambdaExpression было переведено во что-то отличное от двоичного кода (например, в оператор SQL)

2 голосов
/ 20 сентября 2009

Для OR у вас есть два варианта:

  • использование Union / Concat
  • введите Expression в коде

Второй ближе к .Where(x => {a} || {b}).

Если вы используете LINQ-to-SQL, вы можете использовать Expression.Invoke для объединения нескольких отдельных лямбда-выражений ( см. Этот ответ ) - однако, это не поддерживается в Entity Framework. В EF вы должны построить все выражение как один блок, используя Expression.OrElse; например здесь или здесь .

...