Подтвердить что ты не робот

Динамически генерировать запросы LINQ

У нас есть объект

public class SomeObject
{
   public Name {get;set;}
   public City {get;set;}
   public State {get;set}
   //various other parameters.  Let say there ~20
}

Можно ли динамически создавать новые запросы LINQ без перекомпиляции исходного кода? Вместо этого параметры запроса поступают из структуры XML, которая хранится и обновляется в базе данных.

var result = from i in someObj
             where 
             //XML requests Name = 'Bob'...so append this where clause
             name = 'Bob'

Можно ли это сделать?

4b9b3361

Ответ 1

Вот решение с деревьями выражений:

var param = Expression.Parameter(typeof(SomeObject), "p");
var exp = Expression.Lambda<Func<SomeObject, bool>>(
    Expression.Equal(
        Expression.Property(param, "Name"),
        Expression.Constant("Bob")
    ),
    param
);
var query = someObj.Where(exp);

Я знаю, что это намного сложнее, но это может быть полезно в разы.

Ответ 2

Вы наверняка захотите взглянуть на Динамический Linq, который позволит вам определить условия запроса как текст.

Что касается динамических условий добавления, вы можете добавить условия к запросу с использованием аналогичного синтаксиса:

if(CategoryIsImportant)
    myQuery = myQuery.Where("CategoryId=2");

все, что вы можете (довольно легко) кодировать в формате XML по вашему выбору.

Ответ 3

Мне сложно рассказать по вашему вопросу, но в некоторых случаях вам не нужен динамический Linq и он просто может это сделать...

var result = from o in someObj 
             where (Name == null || o.Name == Name)
             && (City == null || o.City == City)
             && (State == null || o.State == State)
             select o;

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

Ответ 5

Я верю, что вам придется фактически копаться в Деревьях выражений. Я не очень сильно укопался в этом, поэтому я не могу создать образец для вас, но я знаю, что вы можете использовать деревья выражений для динамического создания ваших запросов, а затем вызвать .Compile(в коде), чтобы он выполнялся.

На самом деле, вот лучшая ссылка Создание динамических запросов с помощью деревьев выражений. Он должен дать вам именно то, что вы хотите, и достаточно кратким для того, что это. Это должно послужить вам хорошим примером:)

Ответ 6

Я предполагаю, что вы хотите ввести дополнительные фильтры, в зависимости от содержимого вашего XML. Чтобы продолжить на примере StriplingWarrior:

var name = GetNameFromXml();
var city = GetCityFromXml();
var state = GetStateFromXml();

var result = someObj;
if (name != null)
    result = result.Where(i => i.Name == name);
if (city != null)
    result = result.Where(i => i.City == city);
if (state != null)
    result = result.Where(i => i.State == state);

Таким образом, вы будете применять любое количество фильтров (от одного до трех), в зависимости от того, что на самом деле указано в вашем XML.

Ответ 7

Да, на самом деле это довольно просто:

var name = GetBobNameFromXml();
var result = someObj.Where(i => i.Name == name);

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

var result = someObj;
var name = xmlCriteria.Name;
if(!string.IsNullOrEmpty(name))
{
    result = result.Where(i => i.Name == name);
}
// follow the same pattern for city, state, etc.

Вы даже можете использовать шаблон, который использует словарь с ключевыми словами для функций критерия, чтобы избежать кучки операторов if.

foreach(var criterionPair in xmlCriteria)
{
    var value = criterionPair.Value;
    result = result.Where(i => propGetters[criterionPair.PropertyName](i, value));
}

В принципе, вы можете сделать это в этом направлении. Если вы хотите получить более конкретный ответ на вашу ситуацию, вам нужно задать более конкретный вопрос.