使用表达式树进行动态查询

发布于 2024-09-06 18:09:26 字数 1201 浏览 10 评论 0原文

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

  table_name
  columnName_to_sort_by
  columnName_to_search_in

用户应在文本框中输入 Search_text

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

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

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

温暖的光 2024-09-13 18:09:26

你所拥有的很接近。当您问“WHAT_SHOULD_BE_HERE”时,您很好奇使用什么表达式来指示 OrderBy 的“源”参数,当用作扩展方法时,该参数通常从操作数中隐含。您需要做的是将示例更改为对 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

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
一梦浮鱼 2024-09-13 18:09:26

我在 Order by 中遇到了同样的错误。

我查看了 Call 方法,发现我缺少参数 - list.Expression,其中 list 是您的 IQuerable

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文