2010-09-14 5 views
1

Я пытаюсь получить следующий SQL запрос для работы в LINQ:LINQ BuildContainsExpression С ИЛИ условия

Select id from table1 where id in (1,2) or canceledId in (1,2) 

Я использую BuildContainsExpression для достижения «IN» состоянии, но я не могу понять как реализовать условие «или». Мой выстрел в темноте выглядит следующим образом:

var identifiers = new List<int> {1,2}; 

var query = (from t in Context.Table1 
      select t); 

var query = 
    query.Where(BuildContainsExpression<Table1, int>(t => t.Id, identifiers)); 

if (showCanceled) 
{ 
    var expression = query.Where(BuildContainsExpression<Table1, int>(t => t.CanceledId.Value, identifiers)).Expression; 
    Expression.Or(expression, transactionsQuery.Expression); 
} 

Но я получаю следующее исключение:
бинарный оператор Или не определен для типов 'System.Linq.IQueryable 1[Table1]' and 'System.Linq.IQueryable 1 [Table1] ..

Любые идеи? -Я в правильном направлении?

Thanks, Nir.

+1

Вы работаете с Entity Framework в .NET 3.5? – Steven

+0

Да, (3.5 SP1) жаль, что не упоминал об этом. – nirpi

ответ

3

Вы добавляете свое ИЛИ в неположенном месте. То, что вы делаете сейчас фактически что-то вроде этого:

(from t in Context.Table1 
where identifiers.Contains(t.Id) 
select t) 
OR 
(where identifiers.Contains(t.CanceledId)) 

Вторая проблема заключается в том, что BuildContainsExpression метод вы используете, возвращает лямбда-выражение, то, что выглядит следующим образом:

t => t.Id == 1 || t.Id == 2 || ... 

Вы можете» t измените это выражение после его создания. Тем не менее, это то, что вы хотите, потому что вы хотели бы иметь что-то вроде этого:

t => t.Id == 1 || t.Id == 2 || ... || t.CanceledId == 1 || t.CanceledId == 2 || ... 

Вы не можете просто взять тело этого лямбда-выражения и или вместе с другим выражением, поскольку она зависит от параметра t ,

Так что вы можете сделать, это следующее:

// Overload of BuildContainsExpression. 
private static Expression<Func<T, bool>> BuildOtherContainsExpression<T>(
    ParameterExpression p, Expression field1, Expression field2, int[] values) 
{ 
    var eq1 = values.Select(v => Expression.Equal(field1, Expression.Constant(v))); 
    var eq2 = values.Select(v => Expression.Equal(field2, Expression.Constant(v))); 

    var body = eq1.Aggregate((acc, equal) => Expression.Or(acc, equal)); 
    body = eq2.Aggregate(body, (acc, equal) => Expression.Or(acc, equal)); 
    return Expression.Lambda<Func<T, bool>>(body, p); 
} 

// Create a parameter expression that represents something of type Table1. 
var parameter = Expression.Parameter(typeof(Table1), "t"); 

// Create two field expressions that refer to a field of the parameter. 
var idField = Expression.Property(parameter, "Id"); 
var canceledIdField = Expression.Property(parameter, "CanceledId"); 

// And finally the call to this method. 
query.Where(BuildContainsExpression<Table1>(
    parameter, idField, canceledIdField, identifiers)); 

Ваше заявление, если бы выглядеть следующим образом:

if (!showCanceled) 
{ 
    // Use original version of BuildContainsExpression. 
} 
else 
{ 
    // Create some expressions and use overloaded version of BuildContainsExpression. 
} 
+0

Я получаю сообщение об ошибке со средой, где присваивание (Expression.Or): не может неявно преобразовывать тип «System.Linq.Expressions.BinaryExpression» в «System.Linq.Expressions.Expression» > ' В Кроме того, выражение не требуется, поскольку оно уже является выражением, не так ли? – nirpi

+0

Вы правы, и я слишком скоро ответил на ваш вопрос. Работая над решением прямо сейчас. –

+0

Привет, Во-первых, спасибо, что потратили время на эту проблему. Когда я пытаюсь создать поля параметра, я получаю: System.ArgumentException: Поле 'Id' не определено для типа Table1. Когда я проверяю свойства с помощью отражения типа, я вижу 3 свойства: Name, NodeType & Type. – nirpi

1

Я знаю, что я немного опоздал на вечеринку здесь - но Я думаю, что исходный код в исходном постере был прав 99%.

Единственным неправильным было то, что вместо

Expression.Or 

это должно было быть

Expression.OrElse 
Смежные вопросы