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!

Était-ce utile?

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é.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top