Ответ 1
alt text http://www.scottgu.com/blogposts/dynquery/step2.png
Вам нужно что-то вроде этого? Используйте Linq Dynamic Query Library (загрузка включает примеры).
Подробнее блог ScottGu.
Каков наилучший способ собрать динамическое предложение WHERE в оператор LINQ?
У меня есть несколько десятков флажков в форме и передаю их обратно: Словарь < string, List <string → > (Dictionary < fieldName, List < values → ) в мой запрос LINQ.
public IOrderedQueryable<ProductDetail> GetProductList(string productGroupName, string productTypeName, Dictionary<string,List<string>> filterDictionary)
{
var q = from c in db.ProductDetail
where c.ProductGroupName == productGroupName && c.ProductTypeName == productTypeName
// insert dynamic filter here
orderby c.ProductTypeName
select c;
return q;
}
alt text http://www.scottgu.com/blogposts/dynquery/step2.png
Вам нужно что-то вроде этого? Используйте Linq Dynamic Query Library (загрузка включает примеры).
Подробнее блог ScottGu.
Вы также можете использовать PredicateBuilder из LinqKit для объединения нескольких типов лямбда-выражений с использованием Or или And.
Простой подход может быть, если ваши столбцы имеют простой тип, например String
public static IEnumerable<MyObject> WhereQuery(IEnumerable<MyObject> source, string columnName, string propertyValue)
{
return source.Where(m => { return m.GetType().GetProperty(columnName).GetValue(m, null).ToString().StartsWith(propertyValue); });
}
Я придумал решение, которое даже я могу понять... используя метод "Содержит", вы можете объединить столько ГДЕ, сколько захотите. Если WHERE является пустой строкой, она игнорируется (или оценивается как выбор всех). Вот мой пример объединения двух таблиц в LINQ, применения множественных предложений и заполнения класса модели для возврата в представление. (это выбор всех).
public ActionResult Index()
{
string AssetGroupCode = "";
string StatusCode = "";
string SearchString = "";
var mdl = from a in _db.Assets
join t in _db.Tags on a.ASSETID equals t.ASSETID
where a.ASSETGROUPCODE.Contains(AssetGroupCode)
&& a.STATUSCODE.Contains(StatusCode)
&& (
a.PO.Contains(SearchString)
|| a.MODEL.Contains(SearchString)
|| a.USERNAME.Contains(SearchString)
|| a.LOCATION.Contains(SearchString)
|| t.TAGNUMBER.Contains(SearchString)
|| t.SERIALNUMBER.Contains(SearchString)
)
select new AssetListView
{
AssetId = a.ASSETID,
TagId = t.TAGID,
PO = a.PO,
Model = a.MODEL,
UserName = a.USERNAME,
Location = a.LOCATION,
Tag = t.TAGNUMBER,
SerialNum = t.SERIALNUMBER
};
return View(mdl);
}
У меня есть аналогичный сценарий, когда мне нужно добавить фильтры на основе пользовательского ввода, и я связываю предложение where.
Вот пример кода.
var votes = db.Votes.Where(r => r.SurveyID == surveyId);
if (fromDate != null)
{
votes = votes.Where(r => r.VoteDate.Value >= fromDate);
}
if (toDate != null)
{
votes = votes.Where(r => r.VoteDate.Value <= toDate);
}
votes = votes.Take(LimitRows).OrderByDescending(r => r.VoteDate);
У меня был такой же вопрос (Пользовательский фильтр для linq), и @tvanfosson рассказал мне о Dynamic Linq (http://code.msdn.microsoft.com/csharpsamples).
Вы можете использовать метод расширения Any(). Для меня, похоже, работает.
XStreamingElement root = new XStreamingElement("Results",
from el in StreamProductItem(file)
where fieldsToSearch.Any(s => el.Element(s) != null && el.Element(s).Value.Contains(searchTerm))
select fieldsToReturn.Select(r => (r == "product") ? el : el.Element(r))
);
Console.WriteLine(root.ToString());
Где 'fieldsToSearch' и 'fieldsToReturn' являются объектами списка.
Этот проект на CodePlex имеет то, что вы хотите.
System.Linq.Dynamic - http://dynamiclinq.codeplex.com/
Описание проекта
Расширяет System.Linq.Dynamic для поддержки выполнения Лямбда-выражений, определенных в строке с Entity Framework или любым провайдером, поддерживающим IQueryable.
Поскольку это расширение исходного кода, вы можете найти в Scott Guthrie Blog, это позволит вам делать такие вещи:
И такие вещи:
Это решение, с которым я столкнулся, если кому-то это интересно.
https://kellyschronicles.wordpress.com/2017/12/16/dynamic-predicate-for-a-linq-query/
Сначала мы идентифицируем один тип элемента, который нам нужно использовать (из TRow As DataRow), а затем идентифицируем "источник", который мы используем, и привязываем идентификатор к этому источнику ((источник As TypedTableBase (Of TRow)). должен указать предикат или предложение WHERE, которое будет передано (предикат As Func (Of TRow, Boolean)), который либо будет возвращен как истинный, либо false. Затем мы определяем, как мы хотим, чтобы возвращаемая информация упорядочивалась (OrderByField As String). Затем наша функция вернет EnumerableRowCollection (Of TRow), нашу коллекцию datarows, которая удовлетворяет условиям нашего предиката (EnumerableRowCollection (Of TRow)). Это базовый пример. Конечно, вы должны убедиться, что ваше поле заказа не работает содержат нули или правильно обработали эту ситуацию и убедитесь, что имена столбцов (если вы используете сильно типизированный источник данных, не обращайте на это внимания, он переименует столбцы для вас) являются стандартными.