query dinamica usando l'albero delle espressioni

c# dynamic-linq expression-trees

Domanda

Ho un modulo in cui l'utente sceglierà quanto segue dagli elenchi a discesa:

  table_name
  columnName_to_sort_by
  columnName_to_search_in

L'utente deve inserire Search_text in una casella di testo

Il modulo deve trarre dati da molte tabelle. Voglio evitare di scrivere l'ordinamento e cercare ogni campo per ciascuna tabella. Questo è il motivo per cui voglio usare alberi di espressione. Voglio creare la query in modo dinamico.

Voglio scrivere un metodo generico che genererà l'albero delle espressioni per i metodi select , where e orderby , a seconda dell'input dell'utente. Posso usare System.Reflection per ottenere il Type che viene interrogato (tutte le mie tabelle sono di tipo - sto usando LinqToSql).

Non so come formare gli alberi espressione.

Ecco cosa ho finora:

private static List<T> GetSortedData<T>( string sortColumnName) 
{ 
        var type = typeof(T); 
        var property = type.GetProperty(sortColumnName); 
        var parameter = Expression.Parameter(type, "p"); 
        var propertyAccess = Expression.MakeMemberAccess(parameter, property); 
        var orderByExp = Expression.Lambda(propertyAccess, parameter); 
        MethodCallExpression resultExp = Expression.Call(typeof(Queryable), "OrderBy", new Type[] { type, property.PropertyType }, WHAT_SHOULD_BE_HERE, Expression.Quote(orderByExp)); 
        return (List<T>)Expression.Lambda(resultExp).Compile().DynamicInvoke(); 
} 

Come posso implementare select , sort e orderby dinamicamente utilizzando alberi di espressione?

Risposta popolare

Quello che hai è vicino. Dove chiedi "WHAT_SHOULD_BE_HERE", sei curioso di quale espressione utilizzare per indicare il parametro "source" per OrderBy, che di solito è implicito dall'operando quando usato come metodo di estensione. Quello che devi fare è cambiare il tuo campione per operare su IQueryable e devi accettarlo come parametro di input. Inoltre, sostituisci il segnaposto WHAT_SHOULD_BE_HERE con "list.Expression" come mostrato di seguito.

private static IEnumerable<T> GetSortedData<T>(IQueryable<T> list, string sortColumnName) 
{ 
    var type = typeof(T); 
    var property = type.GetProperty(sortColumnName); 
    var parameter = Expression.Parameter(type, "p"); 
    var propertyAccess = Expression.Property(parameter, property); 
    var orderByExp = Expression.Lambda(propertyAccess, parameter); 
    MethodCallExpression resultExp = Expression.Call(typeof(Queryable), "OrderBy", new[] { type, property.PropertyType }, list.Expression, Expression.Quote(orderByExp)); 
    return (IEnumerable<T>)Expression.Lambda(resultExp).Compile().DynamicInvoke(); 
} 

Ho provato questo con il seguente codice:

static void Main(string[] args)
{
    var list = new List<Person>(new[] 
    { 
        new Person { FirstName = "John" }, 
        new Person { FirstName = "Jane" }
    }).AsQueryable();

    foreach (var o in GetSortedData(list, "FirstName")) 
        Console.WriteLine(o.FirstName);
}

public class Person
{
    public string FirstName { get; set; }
}

Quale stampato:

Jane
John


Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
È legale questo KB? Sì, impara il perché