Expression.Or, Der Parameter 'item' ist in ihrem Umfang nicht
-
03-07-2019 - |
Frage
Ich versuche, eine statische Funktion oder zwei Ausdrücke zu schreiben, aber empfange die folgende Fehlermeldung:
Der Parameter 'item' ist in ihrem Umfang nicht.
Beschreibung: Eine nicht behandelte Ausnahme während der Ausführung des aufgetretenen aktuelle Web-Anfrage. Bitte lesen Sie die Stack-Trace für weitere Informationen über der Fehler und wo sie ihren Ursprung in der Code.
Ausnahmedetails: System.InvalidOperationException: Die Parameter 'item' ist in ihrem Umfang nicht.
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 : Mehr Details Hinzufügen
Die Ausdrücke werden im Folgenden aus dem Verfahren kommen, ODER-Verknüpfung, die ganz gut ausführen. wenn es einen besseren Weg zu oder die Ergebnisse ist bin ich ganz Ohr. Auch ich weiß nicht, wie viele werden im Voraus ODER-verknüpft.
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 : Hinzufügen von noch mehr Informationen
Alternativ gibt es einen besseren Weg, um einen oder zu tun? Derzeit ist die .Where (Constraint) funktioniert gut, wo Zwang vom Typ Expression ist>. Wie kann ich tun, wo (constraint1 oder constraint2) (die Einschränkung n-ten)
Vielen Dank im Voraus!
Lösung
Das Problem ist, dass der Ausdruck, den Sie in den Verfahren OrExpressions sind die Schaffung der Körper der beiden Ausdrücke wieder verwendet. Diese Stellen werden Verweise auf ihre eigene Parameterexpression enthalten, die in Filterexpression definiert wurde.
Ein Update wäre die linken und rechten Teile neu zu schreiben, die neue Parameterexpression zu verwenden. Oder die ursprüngliche Parameterexpression passieren entlang. Es ist nicht, weil die beiden Parameterexpression haben den gleichen Namen, dass sie die gleichen Parameter darstellen.
Andere Tipps
Wie bereits angedeutet, Sie diese sehr schön finden (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 gebunden (IMHO) zu LINQ.
Ich bin mir nicht sicher über die richtigen Begriffe hier, aber im Grunde Ausdruck Parameter sind nicht gleichwertig, auch wenn sie die 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 werden nicht dasselbe sein, wenn in einem Ausdruck verwendet.
Der beste Weg, damit umzugehen ist vorne für Ihren Ausdruck einen Parameter erstellen, und dann an alle Helferfunktionen übergibt es, die die Parameter benötigen.
EDIT: Auch, wenn Sie dynamisch sind versuchen, wo Klauseln in LINQ zu komponieren, könnten Sie geben PredicateBuilder versuchen.
Für diejenigen, die diese Seite durch eine Suchmaschine gefunden und wird verwenden die PredicateBuilder von Ben & Joe Albahari , watch out, da es nicht mit dem Rahmen Entity arbeiten .
Versuchen Sie diese feste Version statt.
Fabrizio Lösung kam es auch als gut für mich, aber da ich zwei Ausdrücke zu kombinieren versuche, die als Linq 2 SQL-Abfrage ausgeführt werden würde, dachte ich es eher im Speicher ausgeführt werden würde, als der SQL-Server.
Ich schrieb -. Linq to SQL- erkennt, dass der Aufruf einer Lambda-Ausdruck ist und erzeugt somit noch optimiert SQL