Expression.Or, le paramètre 'item' n'est pas dans la portée
-
03-07-2019 - |
Question
J'essaie d'écrire une fonction statique dans Ou deux expressions, mais je reçois le message d'erreur suivant:
Le paramètre 'item' n'est pas dans la portée.
Description: une exception non gérée eu lieu pendant l'exécution du demande web en cours. S'il vous plaît examiner le trace de pile pour plus d'informations sur l'erreur et où il est originaire le code.
Détails de l'exception: System.InvalidOperationException: Le le paramètre 'item' n'est pas dans la portée.
la méthode:
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);
}
modifier : ajout d'informations supplémentaires
Les expressions en cours ou proviennent de la méthode ci-dessous, qui s'exécute correctement. s'il y a un meilleur moyen ou les résultats, je suis tout ouïe. De plus, je ne sais pas combien il y en a ou sont en avance.
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);
}
modifier : ajouter encore plus d'informations
Sinon, y a-t-il une meilleure façon de faire un ou? Actuellement, la contrainte (.Where) fonctionne parfaitement, où contrainte est de type Expression > ;. Comment puis-je faire où (contrainte1 ou contrainte2) (à la contrainte n'th)
Merci d'avance!
La solution
Le problème est que l'expression que vous créez dans la méthode OrExpressions réutilise le corps des deux expressions. Ces corps contiendront des références à leur propre ParameterExpression définie dans FilterExpression.
Un correctif consisterait à réécrire les parties gauche et droite pour utiliser le nouveau ParameterExpression. Ou pour transmettre la ParameterExpression originale. Ce n'est pas parce que les deux ParameterExpression ont le même nom qu'elles représentent le même paramètre.
Autres conseils
Comme déjà suggéré, ici , vous pouvez trouver ce très beau code (de travail)
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);
}
que vous pouvez adapter à vos besoins et qui n'est pas lié (IMHO) à LINQ.
Je ne suis pas sûr des termes appropriés, mais les paramètres d'expression ne sont pas équivalents même s'ils portent le même nom.
Cela signifie que
var param1 = Expression.Parameter(typeof(T), "item");
var param2 = Expression.Parameter(typeof(T), "item");
param1 != param2
param1 et param2 ne seront pas la même chose s'ils sont utilisés dans une expression.
La meilleure solution consiste à créer un paramètre initial pour votre expression, puis à le transmettre à toutes les fonctions d'assistance nécessitant ce paramètre.
EDIT: si vous essayez de composer dynamiquement des clauses where dans LINQ, vous pouvez donner PredicateBuilder à essayer.
Pour ceux qui ont trouvé cette page à l'aide d'un moteur de recherche et qui utiliseront le PredicateBuilder de Ben & Joe Albahari , faites attention, car il ne fonctionne pas avec Entity Framework .
Essayez cette version corrigée à la place.
La solution de Fabrizio m’est également venue à l’esprit, mais comme j’essayais de combiner deux expressions qui seraient exécutées sous la forme d’une requête linq 2 sql, j’imaginais qu’elle s’exécuterait en mémoire plutôt que sur le serveur SQL.
me suis-je écrit - Linq-To-Sql reconnaît que l’invocation est une expression lambda et produit donc toujours un sql optimisé.