Динамически генерировать запросы 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'
Можно ли это сделать?
Ответы
Ответ 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. И он по-прежнему хорошо работает благодаря короткому замыканию в С#.
Ответ 4
Возможно, Dynamic Linq может помочь вам: Динамическая часть linq 1: Использование библиотеки динамических запросов linq
query = query.Where("Id = 123 And Age > 18");
Или вы можете напрямую манипулировать своим запросом Linq:
query = query.Where(x=>x.Id == 5);
Ответ 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));
}
В принципе, вы можете сделать это в этом направлении. Если вы хотите получить более конкретный ответ на вашу ситуацию, вам нужно задать более конкретный вопрос.