Несколько предложений WHERE с методами расширения LINQ
у меня есть запрос LINQ, который выглядит следующим образом:
DateTime today = DateTime.UtcNow;
var results = from order in context.Orders
where ((order.OrderDate <= today) && (today <= order.OrderDate))
select order;
Я пытаюсь узнать / понять LINQ. В некоторых случаях мне нужно добавить два дополнительных предложения WHERE. В попытке сделать это, я использую:
if (useAdditionalClauses)
{
results = results.Where(o => o.OrderStatus == OrderStatus.Open) // Now I'm stuck.
}
как вы можете видеть, я знаю, как добавить дополнительный пункт WHERE. Но как мне добавить несколько? Например, я хотел бы добавить
WHERE o.OrderStatus == OrderStatus.Open AND o.CustomerID == customerID
к моему предыдущему запросу. Как это сделать с помощью расширения методы?
спасибо!
7 ответов:
два варианта:
results = results.Where(o => (o.OrderStatus == OrderStatus.Open) && (o.CustomerID == customerID));
или:
results = results.Where(o => (o.OrderStatus == OrderStatus.Open)) .Where(o => (o.CustomerID == customerID));
Я обычно предпочитаю последний. Но стоит профилировать SQL server, чтобы проверить выполнение запроса и посмотреть, какой из них лучше работает для ваших данных (если есть какая-либо разница вообще).
примечание о цепочке
.Where()
методы: вы можете связать вместе все методы LINQ, которые вы хотите. Такие методы, как.Where()
на самом деле не выполняется против базы данных (пока). Они отложить исполнение пока фактические результаты вычисляются (например, с помощью.Count()
или.ToList()
). Итак, как вы цепочку вместе несколько методов (больше вызовов.Where()
, возможно.OrderBy()
или что-то в этом роде, и т. д.) они создают то, что называется выражение дерево. Все это дерево является то, что выполняется в источнике данных, когда приходит время, чтобы оценить его.
вы можете продолжать цепочку их, как вы сделали.
results = results.Where (o => o.OrderStatus == OrderStatus.Open); results = results.Where (o => o.InvoicePaid);
это представляет собой и.
если вы работаете с данными в памяти (читайте "коллекции POCO"), вы также можете складывать свои выражения вместе с помощью PredicateBuilder вот так:
// initial "false" condition just to start "OR" clause with var predicate = PredicateBuilder.False<YourDataClass>(); if (condition1) { predicate = predicate.Or(d => d.SomeStringProperty == "Tom"); } if (condition2) { predicate = predicate.Or(d => d.SomeStringProperty == "Alex"); } if (condition3) { predicate = predicate.And(d => d.SomeIntProperty >= 4); } return originalCollection.Where<YourDataClass>(predicate.Compile());
полный источник упомянул
PredicateBuilder
ниже (но вы также можете проверить оригинальные страницы С еще несколькими примерами):using System; using System.Linq; using System.Linq.Expressions; using System.Collections.Generic; public static class PredicateBuilder { public static Expression<Func<T, bool>> True<T> () { return f => true; } public static Expression<Func<T, bool>> False<T> () { return f => false; } public static Expression<Func<T, bool>> Or<T> (this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2) { var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ()); return Expression.Lambda<Func<T, bool>> (Expression.OrElse (expr1.Body, invokedExpr), expr1.Parameters); } public static Expression<Func<T, bool>> And<T> (this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2) { var invokedExpr = Expression.Invoke (expr2, expr1.Parameters.Cast<Expression> ()); return Expression.Lambda<Func<T, bool>> (Expression.AndAlso (expr1.Body, invokedExpr), expr1.Parameters); } }
Примечание: я проверил этот подход с Переносимая Библиотека Классов и
.Compile()
сделать это работа:где(предикат .Компилировать() );
обязательно:
if (useAdditionalClauses) { results = results.Where(o => o.OrderStatus == OrderStatus.Open && o.CustomerID == customerID) }
или просто еще один
.Where()
вызов как этот (хотя я не знаю, почему вы хотите, если он не разделен другой булевой переменной управления):if (useAdditionalClauses) { results = results.Where(o => o.OrderStatus == OrderStatus.Open). Where(o => o.CustomerID == customerID); }
или другое переназначение на : ` = результаты.Где (мля).
вы можете использовать && и записать все условия в том же предложении where, или вы можете .Где.)(Где.)(Где.)(.. и так далее.