Общий предикат запроса LINQ?
Вопрос
Не уверен, возможно ли это или я правильно выражаю то, что ищу, но у меня неоднократно есть следующий фрагмент кода в моей библиотеке, и я хотел бы немного попрактиковаться в DRY.У меня есть набор таблиц SQL Server, которые я запрашиваю на основе простого пользовательского поля поиска ala Google.Я использую LINQ для составления окончательного запроса на основе того, что есть в строке поиска.Я ищу способ использовать дженерики и передаваемые в лямбда-функциях, чтобы создать из этого многоразовую процедуру:
string[] arrayOfQueryTerms = getsTheArray();
var somequery = from q in dataContext.MyTable
select q;
if (arrayOfQueryTerms.Length == 1)
{
somequery = somequery.Where<MyTableEntity>(
e => e.FieldName.StartsWith(arrayOfQueryTerms[0]));
}
else
{
foreach(string queryTerm in arrayOfQueryTerms)
{
if (!String.IsNullOrEmpty(queryTerm))
{
somequery = somequery
.Where<MyTableEntity>(
e => e.FieldName.Contains(queryTerm));
}
}
}
Я надеялся создать универсальный метод с сигнатурой, который выглядит примерно так:
private IQueryable<T> getQuery(
T MyTableEntity, string[] arrayOfQueryTerms, Func<T, bool> predicate)
Я использую одну и ту же стратегию поиска во всех своих таблицах, поэтому единственное, что действительно отличается от использования к использованию, - это поиск по MyTable & MyTableEntity и поиск по FieldName.Есть ли в этом смысл?Есть ли способ с помощью LINQ динамически передавать имя поля для запроса в предложении where?Или я могу передать это как лямбда-предикат?
e => e.FieldName.Contains(queryTerm)
Я понимаю, что есть полтора миллиона способов сделать это в SQL, возможно, проще, но я бы хотел сохранить все в семействе LINQ для этого.Кроме того, я считаю, что дженерики должны быть удобны для решения подобной проблемы.Есть какие-нибудь идеи?
Решение
Похоже, вы ищете динамический Linq.Взгляните здесь.Это позволяет вам передавать строки в качестве аргументов методам запроса, таким как:
var query = dataSource.Where("CategoryID == 2 && UnitPrice > 3")
.OrderBy("SupplierID");
Редактировать:Еще один набор постов на эту тему, использующий динамическую поддержку C # 4: Часть 1 и Часть 2.
Другие советы
Похоже, вам нужен в основном конструктор условных предикатов..
Я надеюсь, что вы сможете превратить это во что-то, что ищете, удачи!
Возможно, вы захотите взглянуть на деревья выражений:
IQueryable<T> getQuery<T>(T myTableEntity, string[] arrayOfQueryTerms, Expression<Func<T, bool>> predicate)
{ var fieldOrProperty = getMemberInfo(predicate);
/* ... */
}
MemberInfo getmemberInfo<T>(Expression<Func<T,bool> expr)
{ var memberExpr = expr as MemberExpression;
if (memberExpr != null) return memberExpr.Member;
throw new ArgumentException();
}
var q = getQuery<FooTable>(foo, new[]{"Bar","Baz"}, x=>x.FieldName);
Недавно мне пришлось проделать то же самое.Вам понадобится Динамический Linq здесь это способ сохранить эту строгую типизацию.