2009-01-04 9 views
8

Ich versuche, eine statische Funktion oder zwei Ausdrücke zu schreiben, aber empfangen die folgende Fehlermeldung:Expression.Or, Der Parameter ‚item‘ ist in ihrem Umfang nicht

The parameter 'item' is not in scope.

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidOperationException: The parameter 'item' is not in scope.

die Methode:

public static Expression<Func<T, bool>> OrExpressions(Expression<Func<T, bool>> left, Expression<Func<T, bool>> right) 
{ 
    // Define the parameter to use 
    var param = Expression.Parameter(typeof(T), "item"); 

    var filterExpression = Expression.Lambda<Func<T, bool>> 
     (Expression.Or(
      left.Body, 
      right.Body 
     ), param); 
    // Build the expression and return it 
    return (filterExpression); 
} 

bearbeiten: Hinzufügen von mehr Info

die Ausdrücke aus dem Verfahren werden ODER-verknüpft sind unten, die ganz gut ausführen kommen. Wenn es einen besseren Weg zu den Ergebnissen gibt, bin ich ganz Ohr. Ich weiß auch nicht, wie viele im Voraus sind.

public static Expression<Func<T, bool>> FilterExpression(string filterBy, object Value, FilterBinaryExpression binaryExpression) 
{ 
    // Define the parameter to use 
    var param = Expression.Parameter(typeof(T), "item"); 

    // Filter expression on the value 
    switch (binaryExpression) 
    { 
     case FilterBinaryExpression.Equal: 
      { 
       // Build an expression for "Is the parameter equal to the value" by employing reflection 
       var filterExpression = Expression.Lambda<Func<T, bool>> 
        (Expression.Equal(
         Expression.Convert(Expression.Property(param, filterBy), typeof(TVal)), 
         Expression.Constant(Value) 
        ), 
        param); 
       // Build the expression and return it 
       return (filterExpression); 
      } 

bearbeiten: indem noch mehr Infos

Alternativ gibt es einen besseren Weg, um einen oder zu tun? Derzeit funktioniert die .Where (constraint) genau dort, wo die Bedingung vom Typ Expression> ist. Wie kann ich wo tun (constraint1 oder constraint2) (zur constraint n'th)

Vielen Dank im Voraus!

Antwort

9

Das Problem besteht darin, dass der Ausdruck, den Sie in der Methode OrExpressions erstellen, den Text der beiden Ausdrücke wieder verwendet. Diese Körper enthalten Verweise auf ihre eigene ParameterExpression, die in FilterExpression definiert wurde.

Eine Korrektur wäre, die linken und rechten Teile neu zu schreiben, um den neuen ParameterExpression zu verwenden. Oder um den ursprünglichen ParameterExpression mitzugeben. Es liegt nicht daran, dass die beiden ParameterExpression denselben Namen haben, da sie den gleichen Parameter darstellen.

+0

Vielen Dank! Gehen – ccook

+0

Sie mein Freund, um zu versuchen und jetzt den gleichen Parameter übergeben, sind erstaunlich :) – ccook

2

Ich bin nicht sicher über die richtigen Begriffe hier, aber im Grunde Ausdruck Parameter sind nicht gleichwertig, auch wenn sie den gleichen Namen haben.

Das bedeutet, dass

var param1 = Expression.Parameter(typeof(T), "item"); 
var param2 = Expression.Parameter(typeof(T), "item"); 

param1 != param2 

param1 und param2 wird nicht dasselbe sein, wenn in einem Ausdruck verwendet.

Der beste Weg, damit umzugehen, ist, einen Parameter für Ihren Ausdruck zu erstellen und ihn dann an alle Hilfsfunktionen zu übergeben, die den Parameter benötigen.

EDIT: Auch wenn Sie versuchen, where Klauseln in LINQ dynamisch zu komponieren, könnten Sie PredicateBuilder versuchen.

+0

Danke :) ich die Methode in der gleichen Parameter an die Helfer Methoden übergeben überarbeitet und alles ist wieder gut. Ich bin auf der Suche in die PredicateBuilder hoffentlich sauber Dinge – ccook

+0

Pass auf, da die PredicateBuilder von Ben & Joe Albahari funktioniert nicht für Entity Framework. Siehe meine Antwort für eine feste Version. –

4

Wie bereits angedeutet, here diese schöne (in Betrieb) Code

public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2) 
{ 
    var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>()); 
    return Expression.Lambda<Func<T, bool>>(Expression.Or(expr1.Body, invokedExpr), expr1.Parameters); 
} 

, die Sie an Ihre Bedürfnisse anpassen können und welche nicht (IMHO) gebunden zu LINQ finden.

+0

Schön und sauber, ty – ccook

+0

Achtung, da dieser Code nicht für Entity Framework funktioniert. Siehe meine Antwort für eine feste Version. –

1

Fabrizios Lösung kam mir auch in den Sinn, aber da ich versuchte, zwei Ausdrücke zu kombinieren, die als eine linq 2-SQL-Abfrage ausgeführt würden, dachte ich, sie würde im Speicher statt auf dem SQL-Server ausgeführt werden.

Ich wurde geschrieben - Linq-To-Sql erkennt, dass der Aufruf von einem Lambda-Ausdruck ist und somit immer noch optimierte SQL erzeugt.

2

Für diejenigen, die diese Seite durch eine Suchmaschine gefunden und wird die PredicateBuilder von Ben & Joe Albahari zu verwenden, achten, da es nicht mit dem Entity Framework arbeiten.

Versuchen this fixed version statt.