Domanda

Sto provando a scrivere una funzione statica su O due espressioni, ma ricevo il seguente errore:

  

Il parametro 'item' non rientra nell'ambito.

     

Descrizione: un'eccezione non gestita   si è verificato durante l'esecuzione del   richiesta web corrente. Si prega di rivedere il   stack stack per ulteriori informazioni su   l'errore e la sua origine   il codice.

     

Dettagli eccezione:   System.InvalidOperationException: The   il parametro 'item' non rientra nell'ambito.

il metodo:

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);
}

modifica : aggiunta di ulteriori informazioni

Le espressioni essendo o verrebbero dal metodo seguente, che viene eseguito correttamente. se c'è un modo migliore per o i risultati sono tutto orecchie. Inoltre, non so quanti ne siano stati o lo farebbero in anticipo.

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);
            }

modifica : aggiunta di ulteriori informazioni

In alternativa, c'è un modo migliore per fare un o? Attualmente il .Where (vincolo) funziona perfettamente quando il vincolo è di tipo Expression > ;. Come posso fare dove (vincolo1 o vincolo2) (al vincolo n)

Grazie in anticipo!

È stato utile?

Soluzione

Il problema è che l'espressione che stai creando nel metodo OrExpressions riutilizza il corpo delle due espressioni. Tali corpi conterranno riferimenti alla propria ParameterExpression che è stata definita in FilterExpression.

Una correzione sarebbe quella di riscrivere le parti sinistra e destra per usare il nuovo ParameterExpression. Oppure per passare l'espressione ParameterExpression originale. Non è perché i due ParameterExpression hanno lo stesso nome che rappresentano lo stesso parametro.

Altri suggerimenti

Come già suggerito, qui puoi trovare questo bellissimo codice (funzionante)

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);
}

che puoi adattare alle tue esigenze e che non è legato (IMHO) a LINQ.

Non sono sicuro dei termini corretti qui, ma sostanzialmente i parametri di espressione non sono equivalenti anche se hanno lo stesso nome.

Ciò significa che

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

param1 != param2

param1 e param2 non saranno la stessa cosa se usati in un'espressione.

Il modo migliore per gestirlo è creare un parametro in anticipo per la tua espressione, quindi passarlo a tutte le funzioni di supporto che richiedono il parametro.

EDIT: Inoltre, se stai cercando di comporre dinamicamente le clausole where in LINQ, potresti dare PredicateBuilder una prova.

Per coloro che hanno trovato questa pagina da un motore di ricerca e useranno PredicateBuilder di Ben & amp; Joe Albahari , attenzione, poiché non funziona con Entity Framework .

Prova questa versione fissa invece.

Anche la soluzione di Fabrizio mi è venuta in mente, ma dal momento che stavo tentando di combinare due espressioni che sarebbero state eseguite come una query linq 2 sql, ho pensato che sarebbe stato eseguito in memoria piuttosto che nel server sql.

Sono stato scritto - Linq-To-Sql riconosce che l'invocazione è un'espressione lambda e quindi produce ancora sql ottimizzato.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top