Динамический LINQ - есть ли версия .NET 4? - PullRequest
31 голосов
/ 02 марта 2011

Я хочу использовать LINQ для некоторых процедур поиска и хотел бы иметь некоторые динамические предложения where. Так, например, если пользователь хочет выполнить поиск по городу или поиск по штатам, у меня будет динамический вызов LINQ Where <> вместо создания двух строго типизированных выражений LINQ, а затем использование соответствующего выражения в зависимости от того, как пользователь хочет выполнить поиск .

Итак, я хотел бы сделать это:

String criteria="p.City='Pittsburgh'";  //or "p.State='PA'"
personData.Where(criteria)

вместо

personData.Where(p => p.City=="Pittsburgh");

или

personData.Where(p => p.State=="PA");

Я наткнулся на сообщение в блоге Скотта Гатри, рассказывающее о Dynamic LINQ в примерах Visual Studio 2008. Кажется, это делает то, что я хочу, но мои вопросы:

  1. Поддерживается ли этот образец библиотеки Microsoft?
  2. Статья Скотта Гатри относится к VS2008 (.NET 3.5). Есть ли лучший вариант для .NET 4? Может быть, что-то, что было выпущено с .NET 4, которое выполняет то же самое (или что-то очень близкое)?

Заранее спасибо!

Ответы [ 4 ]

9 голосов
/ 02 марта 2011

Возможно, вы захотите взглянуть на PredicateBuilder

6 голосов
/ 03 марта 2011

Эту функцию было бы очень приятно иметь. Аналогичная функция существует в ADO.net Datatables . Это было бы действительно полезно для LinqToSql . Конечно, вы потеряете строго типизированную проверку, но в этом весь смысл, вы хотите динамический поиск. Если вы правильно обработаете исключения, я действительно считаю, что это особенность, которую стоит иметь.

Возможно, вы захотите добавить запрос функции в Microsoft Connect . Библиотека уже существует, возможно, они рассмотрят возможность добавления официальной поддержки для нее. Если вы делаете запрос на функцию, убедитесь, что вы разместили здесь ссылку, чтобы мы могли проголосовать за нее. Microsoft Connect имеет систему голосования, похожую на stackoverflow. Я сам отправил несколько LinqtoSql TableUpdate и VB.net только для чтения интерфейсов, таких как C # .

Я помню, что у меня были проблемы с этой библиотекой. Я думаю, что это как-то связано со статическими методами.

Я нашел, что лучше разработать выражения, которые мне нужны. Эта статья Ильи Биллюка демонстрирует пользовательские выражения. Хорошая вещь в фреймворке Ильи - он удаляет много стандартного кода при выполнении таких операций, как сортировка для jqGrid.

Я обнаружил, что это чрезвычайно полезно при изучении основных понятий выражений.

Приятной особенностью этого кода является то, что он позволяет использовать операторы точки для геттеров. Person.Age или если вы хотите нарушить Деметру, вы можете даже сделать несколько геттеров.

Код можно улучшить. Я считаю, что я добавил StartsWith и разрешил его только для строковых операций, а также для некоторых других поисковых операций. Несмотря на то, что это стоит посмотреть, это помогло мне понять выражения linq.

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

Перечислитель WhereOperation:

public enum WhereOperation { Equal, NotEqual, Contains }
4 голосов
/ 17 января 2014

Теперь он должен быть доступен. Я мог бы скачать его через NuGet: http://www.nuget.org/packages/System.Linq.Dynamic/

1 голос
/ 02 марта 2011

Я не думаю, что он «поддерживается» Microsoft - похоже, он выпущен под публичной лицензией, которая частично гласит:

(E) Программное обеспечение лицензируется «как есть». Вы несете риск его использования. Авторы не дают выразить гарантии, гарантии или условия. У вас может быть дополнительный потребитель права в соответствии с местными законами, которые эта лицензия не может быть изменена. К в пределах вашей территории законы, авторы исключают подразумеваемые гарантии товарности, пригодность для определенной цели и ненарушения.

На ваш второй вопрос, я не думаю, что есть версия .NET 4. 3.5 должен нормально работать в проекте 4.0, и я не думаю, что в него можно что-то добавить. Насколько я понимаю, это была небольшая изящная библиотека для выполнения случайных одноразовых запросов linq на основе строк. Возможно, вы по какой-то причине вручную сортировали сетку, и вам нужно было изменить порядок сортировки ваших коллекций на основе строки, представляющей рассматриваемое свойство. Вуаля. Я сомневаюсь, что вы приложите немало усилий, чтобы добавить в него множество функций.

...