简体   繁体   中英

dynamic query using expression tree

I have a form in which the user will choose the following from dropdown lists:

  table_name
  columnName_to_sort_by
  columnName_to_search_in

The user shall enter Search_text in a text box

The form shall draw data from many tables. I want to avoid writing the sort and search for every field for each of the tables. This is why I want to use expression trees. I want to build the query dynamically.

I want to write a generic method that will generate the expression tree for the select , where and orderby methods, depending on user input. I can use System.Reflection to get the Type that is being queried (all my tables are types - I am using LinqToSql).

I do not know how to form the expression trees.

Here's what I have so far:

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

How can I implement select , sort and orderby dynamically using expression trees?

What you have is close. Where you ask, "WHAT_SHOULD_BE_HERE", you are curious what expression to use to indicate the "source" parameter for OrderBy, which is usually implied from the operand when used as an extension method. What you need to do is change your sample to operate on IQueryable, and you need to accept that as an input parameter. Also, replace your WHAT_SHOULD_BE_HERE placeholder with "list.Expression" as shown below.

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

I tested this with the following code:

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

Which printed out:

Jane
John

I was facing the same Error with Order by .

I looked into the Call method and found that I was missing the Parameter -- list.Expression , where list is your IQuerable

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM