Общий предикат запроса 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 для этого. Кроме того, я считаю, что дженерики должны быть удобными для такой проблемы. Любые идеи?
Ответы
Ответ 1
Похоже, вы ищете Dynamic Linq. Посмотрите здесь. Это позволяет передавать строки в качестве аргументов методам запроса, например:
var query = dataSource.Where("CategoryID == 2 && UnitPrice > 3")
.OrderBy("SupplierID");
Изменить: еще один набор сообщений на эту тему, используя поддержку С# 4 Dynamic: Часть 1 и Часть 2.
Ответ 2
Похоже, вы хотите создать условный построитель предикатов..
Надеюсь, ты сможешь сформировать это во что-то, что ты ищешь, удачи!
http://www.albahari.com/nutshell/predicatebuilder.aspx
Ответ 3
Вы можете посмотреть деревья выражений:
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);
Ответ 4
Недавно мне пришлось сделать то же самое. Вам понадобится Динамический Linq здесь - это способ держите это строго типизированным.