使用表达式树的动态查询

时间:2010-06-24 17:22:14

标签: c# expression-trees dynamic-linq

我有一个表单,用户将从下拉列表中选择以下内容:

  table_name
  columnName_to_sort_by
  columnName_to_search_in

用户应在文本框中输入Search_text

表格应从许多表格中提取数据。我想避免编写排序并搜索每个表的每个字段。这就是我想使用表达式树的原因。我想动态构建查询。

我想编写一个通用方法,根据用户输入生成selectwhereorderby方法的表达式树。我可以使用System.Reflection来获取正在查询的Type(我的所有表都是类型 - 我使用的是LinqToSql)。

我不知道如何形成表达式树。

这是我到目前为止所拥有的:

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

如何使用表达式树动态实现selectsortorderby

2 个答案:

答案 0 :(得分:1)

你所拥有的是亲密的。如果你问“WHAT_SHOULD_BE_HERE”,你很好奇用什么表达式来表示OrderBy的“source”参数,当用作扩展方法时,它通常隐含在操作数中。您需要做的是更改样本以在IQueryable上操作,并且您需要接受它作为输入参数。另外,将WHAT_SHOULD_BE_HERE占位符替换为“list.Expression”,如下所示。

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

我使用以下代码对此进行了测试:

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

打印出来的:

Jane
John

答案 1 :(得分:0)

我遇到了与Order by相同的错误。

我查看了Call方法,发现我错过了参数 - list.Expression,其中列表是您的IQuerable