C# 具有 LINQ 扩展方法的多个 WHERE 子句
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/8791540/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Multiple WHERE Clauses with LINQ extension methods
提问by user609886
I have a LINQ query that looks like the following:
我有一个如下所示的 LINQ 查询:
DateTime today = DateTime.UtcNow;
var results = from order in context.Orders
where ((order.OrderDate <= today) && (today <= order.OrderDate))
select order;
I am trying to learn / understand LINQ. In some cases, I need to add two additional WHERE clauses. In an effort to do this, I'm using:
我正在尝试学习/理解 LINQ。在某些情况下,我需要添加两个额外的 WHERE 子句。为了做到这一点,我正在使用:
if (useAdditionalClauses)
{
results = results.Where(o => o.OrderStatus == OrderStatus.Open) // Now I'm stuck.
}
As you can see, I know how to add an additional WHERE clause. But how do I add multiple? For instance, I'd like to add
如您所见,我知道如何添加额外的 WHERE 子句。但是如何添加多个?例如,我想添加
WHERE o.OrderStatus == OrderStatus.Open AND o.CustomerID == customerID
WHERE o.OrderStatus == OrderStatus.Open AND o.CustomerID == customerID
to my previous query. How do I do this using extension methods?
到我之前的查询。我如何使用扩展方法来做到这一点?
Thank you!
谢谢!
采纳答案by David
Two ways:
两种方式:
results = results.Where(o => (o.OrderStatus == OrderStatus.Open) &&
(o.CustomerID == customerID));
or:
或者:
results = results.Where(o => (o.OrderStatus == OrderStatus.Open))
.Where(o => (o.CustomerID == customerID));
I usually prefer the latter. But it's worth profiling the SQL server to check the query execution and see which one performs better for your data (if there's any difference at all).
我通常更喜欢后者。但是值得分析 SQL 服务器以检查查询执行并查看哪个对您的数据执行更好(如果有任何差异)。
A note about chaining the .Where()methods: You can chain together all the LINQ methods you want. Methods like .Where()don't actually execute against the database (yet). They defer executionuntil the actual results are calculated (such as with a .Count()or a .ToList()). So, as you chain together multiple methods (more calls to .Where(), maybe an .OrderBy()or something to that effect, etc.) they build up what's called an expression tree. This entire tree is what gets executed against the data source when the time comes to evaluate it.
关于链接.Where()方法的注意事项:您可以将所需的所有 LINQ 方法链接在一起。像.Where()这样的方法实际上并不针对数据库执行(还)。它们推迟执行,直到计算出实际结果(例如使用 a.Count()或 a .ToList())。因此,当您将多个方法链接在一起时(对 的更多调用.Where(),可能是一个.OrderBy()或类似的东西,等等),它们会构建所谓的表达式树。当需要对数据源进行评估时,这整个树就是针对数据源执行的。
回答by cadrell0
Just use the &&operator like you would with any other statement that you need to do boolean logic.
只需&&像使用其他任何需要执行布尔逻辑的语句一样使用运算符即可。
if (useAdditionalClauses)
{
results = results.Where(
o => o.OrderStatus == OrderStatus.Open
&& o.CustomerID == customerID)
}
回答by Andras Zoltan
Surely:
一定:
if (useAdditionalClauses)
{
results =
results.Where(o => o.OrderStatus == OrderStatus.Open &&
o.CustomerID == customerID)
}
Or just another .Where()call like this one (although I don't know why you would want to, unless it's split by another boolean control variable):
或者只是.Where()像这样的另一个调用(虽然我不知道你为什么想要,除非它被另一个布尔控制变量分割):
if (useAdditionalClauses)
{
results = results.Where(o => o.OrderStatus == OrderStatus.Open).
Where(o => o.CustomerID == customerID);
}
Or another reassignment to results: `results = results.Where(blah).
或者另一种重新分配results:`results = results.Where( blah)。
回答by Bryan Boettcher
You can continue chaining them like you've done.
您可以像以前一样继续链接它们。
results = results.Where (o => o.OrderStatus == OrderStatus.Open);
results = results.Where (o => o.InvoicePaid);
This represents an AND.
这代表一个 AND。
回答by Gent
results = context.Orders.Where(o => o.OrderDate <= today && today <= o.OrderDate)
The select is uneeded as you are already working with an order.
由于您已经在处理订单,因此不需要选择。
回答by Josh C.
you can use && and write all conditions in to the same where clause, or you can .Where().Where().Where()... and so on.
您可以使用 && 并将所有条件写入相同的 where 子句,或者您可以 .Where().Where().Where()... 等等。
回答by Sevenate
If you working with in-memory data (read "collections of POCO") you may also stack your expressions together using PredicateBuilderlike so:
如果您使用内存数据(阅读“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());
The full source of mentioned PredicateBuilderis bellow (but you could also check the original pagewith a few more examples):
提到的完整来源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);
}
}
Note: I've tested this approach with Portable Class Libraryproject and have to use .Compile()to make it work:
注意:我已经使用便携式类库项目测试了这种方法,并且必须使用.Compile()它才能使其工作:
Where(predicate .Compile());
Where(谓词.Compile());

