2010-06-24 12 views
0

J'ai une forme dans laquelle l'utilisateur choisira les éléments suivants de listes déroulantes:requête dynamique en utilisant l'arbre d'expression

table_name 
    columnName_to_sort_by 
    columnName_to_search_in 

L'utilisateur entre Search_text dans une zone de texte

Le formulaire établit les données de beaucoup de tables. Je veux éviter d'écrire le tri et rechercher tous les champs pour chacune des tables. C'est pourquoi je veux utiliser des arbres d'expression. Je veux construire la requête dynamiquement.

Je veux écrire une méthode générique qui va générer l'arbre d'expression pour les select, where et orderby méthodes, en fonction de l'entrée utilisateur. Je peux utiliser System.Reflection pour obtenir le Type qui est interrogé (toutes mes tables sont des types - j'utilise LinqToSql).

Je ne sais pas comment former les arbres d'expression.

Voici ce que j'ai jusqu'à présent:

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

Comment puis-je mettre en œuvre select, sort et orderby dynamiquement en utilisant des arbres d'expression?

Répondre

1

Ce que vous avez est proche. Lorsque vous demandez, "WHAT_SHOULD_BE_HERE", vous êtes curieux de savoir quelle expression utiliser pour indiquer le paramètre "source" pour OrderBy, qui est généralement implicite de l'opérande lorsqu'il est utilisé comme méthode d'extension. Ce que vous devez faire est de changer votre échantillon pour fonctionner sur IQueryable, et vous devez l'accepter comme un paramètre d'entrée. Remplacez également votre espace réservé WHAT_SHOULD_BE_HERE par "list.Expression" comme indiqué ci-dessous.

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

J'ai testé cela avec le code suivant:

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

qui imprimé:

Jane 
John 
+0

possible d'avoir plusieurs colonnes Trier par – user145610

0

Je faisais face à la même erreur avec Order by.

J'ai regardé dans la méthode Call et a constaté que je manquais le paramètre - list.Expression, où la liste est votre IQuerable