Где я могу найти хороший пример использования выражений linq & lambda для создания динамических где и порядок SQL? - PullRequest
1 голос
/ 21 марта 2012

где я могу найти хороший пример использования выражений linq & lambda для генерации динамического sql? Например, мне нужен метод, чтобы принять эти параметры

GoupOperator ('And' or 'OR')
A list of objects each with the following parameters:
    SearchColumn.
    SearchValue.
    SearchOperator (equals, contains, does not equal ...)

И еще один способ упорядочить любой конкретный столбец по возрастанию или по убыванию

Если на этот вопрос был дан правильный ответ, я с удовольствием его удалю - ни один из предыдущих ответов, которые я видел, не является достаточно полным для того, чтобы новичок в выражениях linq мог без проблем подключиться к существующему приложению - спасибо

Ответы [ 3 ]

5 голосов
/ 24 марта 2012

Я нашел пару методов расширения linq (общие методы Where и OrderBy, написанные Ильей Биллюком, которые принимают имя столбца, значение поиска и операции поиска, а также оператор группировки) в codeproject здесь , который показывает, как это сделатьэто используя asp.net mvc.методы создают дерево динамических выражений - очень элегантное решение.Поскольку я начал использовать традиционный веб-сервис asmx, я использовал его помощников в своем проекте и просто внес несколько изменений, чтобы запустить его здесь -

Вот 2 метода

public static class LinqExtensions
{
    /// <summary>Orders the sequence by specific column and direction.</summary>
    /// <param name="query">The query.</param>
    /// <param name="sortColumn">The sort column.</param>
    /// <param name="ascending">if set to true [ascending].</param>
    public static IQueryable<T> OrderBy<T>(this IQueryable<T> query, string sortColumn, string direction)
    {
        string methodName = string.Format("OrderBy{0}",
            direction.ToLower() == "asc" ? "" : "descending");

        ParameterExpression parameter = Expression.Parameter(query.ElementType, "p");

        MemberExpression memberAccess = null;
        foreach (var property in sortColumn.Split('.'))
            memberAccess = MemberExpression.Property
               (memberAccess ?? (parameter as Expression), property);

        LambdaExpression orderByLambda = Expression.Lambda(memberAccess, parameter);

        MethodCallExpression result = Expression.Call(
                  typeof(Queryable),
                  methodName,
                  new[] { query.ElementType, memberAccess.Type },
                  query.Expression,
                  Expression.Quote(orderByLambda));

        return query.Provider.CreateQuery<T>(result);
    }


    public static IQueryable<T> Where<T>(this IQueryable<T> query,
        string column, object value, WhereOperation operation)
    {
        if (string.IsNullOrEmpty(column))
            return query;

        ParameterExpression parameter = Expression.Parameter(query.ElementType, "p");

        MemberExpression memberAccess = null;
        foreach (var property in column.Split('.'))
            memberAccess = MemberExpression.Property
               (memberAccess ?? (parameter as Expression), property);

        //change param value type
        //necessary to getting bool from string
        ConstantExpression filter = Expression.Constant
            (
                Convert.ChangeType(value, memberAccess.Type)
            );

        //switch operation
        Expression condition = null;
        LambdaExpression lambda = null;
        switch (operation)
        {
            //equal ==
            case WhereOperation.Equal:
                condition = Expression.Equal(memberAccess, filter);
                lambda = Expression.Lambda(condition, parameter);
                break;
            //not equal !=
            case WhereOperation.NotEqual:
                condition = Expression.NotEqual(memberAccess, filter);
                lambda = Expression.Lambda(condition, parameter);
                break;
            //string.Contains()
            case WhereOperation.Contains:
                condition = Expression.Call(memberAccess,
                    typeof(string).GetMethod("Contains"),
                    Expression.Constant(value));
                lambda = Expression.Lambda(condition, parameter);
                break;
        }


        MethodCallExpression result = Expression.Call(
               typeof(Queryable), "Where",
               new[] { query.ElementType },
               query.Expression,
               lambda);

        return query.Provider.CreateQuery<T>(result);
    }
}

Ниже, как я использовал эти методы, возвращаемый объект - это просто пользовательский объект, который передает данные в сетку на стороне клиента

public class Service1 : System.Web.Services.WebService
{
    [WebMethod]
    [ScriptMethod(ResponseFormat = ResponseFormat.Json)]
    public JgGrid SearchGrid(int rows, int page, string sidx, string sord,string filters)
    {
        AdvWorksDataContext dc = new AdvWorksDataContext();
        JavaScriptSerializer serializer = new JavaScriptSerializer();
        filters f = serializer.Deserialize<filters>(filters);

        var p = dc.vProductAndDescriptions.AsQueryable();
        if (f.groupOp == "AND")
            foreach (var rule in f.rules)
                p = p.Where<vProductAndDescription>(
                    rule.field, rule.data,
                    (WhereOperation)StringEnum.Parse(typeof(WhereOperation), rule.op)
                    );
        else
        { 
            //Or
            var temp = (new List<vProductAndDescription>()).AsQueryable();
            foreach (var rule in f.rules)
            {
                var t = p.Where<vProductAndDescription>(
                    rule.field, rule.data,
                    (WhereOperation)StringEnum.Parse(typeof(WhereOperation), rule.op)
                    );
                temp = temp.Concat<vProductAndDescription>(t);
            }
            p = temp;
        }
        p = p.OrderBy<vProductAndDescription>(sidx, sord);

        return new JgGrid(page, p, rows);
    }
}
1 голос
/ 21 марта 2012

Мне кажется, что вы пытаетесь создать провайдера linq ... Попробуйте проверить эту серию руководств о том, как реализовать пользовательский поставщик Linq to SQL: LINQ: создание серии поставщиков IQueryable

1 голос
/ 21 марта 2012

Для случаев, когда у меня много столбцов, для которых требуется динамическая композиция запросов, я использую Dynamic Linq. Это библиотека, написанная в качестве примера для .net 3.5, и она иллюстрирует, как можно писать расширения linq, которые работают с деревом выражений.

Может также использоваться для составления динамических запросов на основе строк, полученных от клиента, таких как имена столбцов, сортировка и т. Д.

Вот ссылка на статью, опубликованную Скоттом Гатри http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

В статье вы найдете ссылки на библиотеку примеров, в которой содержится исходный код библиотеки Dynamic Linq.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...