динамический запрос с использованием дерева выражений

У меня есть форма, в которой пользователь будет выбирать из выпадающих списков следующее:

  table_name
  columnName_to_sort_by
  columnName_to_search_in

Пользователь должен ввести Search_text в текстовое поле

Форма должна извлекать данные из множества таблиц. Я хочу избежать написания сортировки и поиска по каждому полю для каждой из таблиц. Вот почему я хочу использовать деревья выражений. Я хочу построить запрос динамически.

Я хочу написать общий метод, который будет генерировать дерево выражений для методов select, where и orderby в зависимости от ввода пользователя. Я могу использовать 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(); 
} 

Как я могу реализовать select, sort и orderby динамически, используя деревья выражений?


person user375492    schedule 24.06.2010    source источник


Ответы (2)


То, что у вас есть, близко. Когда вы спрашиваете «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
person Kirk Woll    schedule 07.08.2010
comment
Любой способ иметь несколько столбцов в Sort by - person user145610; 04.05.2013

Я столкнулся с той же ошибкой с Order by.

Я изучил метод Call и обнаружил, что мне не хватает параметра -- list.Expression, где список - это ваш IQuerable.

person Neetin    schedule 22.03.2012