嵌套或使用Linq PredicateBuilder [英] Nesting OR using Linq PredicateBuilder
问题描述
我正在使用谓词生成器来编写以下代码:
I am using predicate builder to write the following code:
IEnumerable<int> ids= new List<int> { 47, 48 };
var predicate = PredicateBuilder.False<Customer>();
predicate = predicate.And(x => x.CreatedAt >= fromDate && x.CreatedAt <= toDate);
foreach (var id in ids)
{
predicate = predicate.Or(x => x.Source.Id == id);
}
var result = Database.Set<Customer>().AsExpandable()
.Where(predicate)
.ToList();
生成的SQL看起来像(只是WHERE子句):
The SQL generated looks like (just the WHERE clause):
WHERE ([Filter6].[SourceId] IN (@p__linq__0,@p__linq__1))
AND ([Filter6].[CreatedAt] >= @p__linq__2)
AND ([Filter6].[CreatedAt] <= @p__linq__3)',
N'@p__linq__0 int,
@p__linq__1 int,
@p__linq__2 datetime2(7),
@p__linq__3 datetime2(7)',
@p__linq__0=48,
@p__linq__1=48,
@p__linq__2='2012-02-07 21:59:55.0437985',
@p__linq__3='2012-02-07 22:04:55.5748288'
似乎ID 48在SQL中分配了两次.不知道为什么吗?
It looks like id 48 got assigned twice in the SQL. Not sure why?
推荐答案
foreach (var id in ids)
{
predicate = predicate.Or(x => x.Source.Id == id);
}
您正在关闭循环变量.改为创建您的id
变量的本地副本:
You are closing over the loop variable. Make a local copy of your id
variable instead:
foreach (var id in ids)
{
int localId = id;
predicate = predicate.Or(x => x.Source.Id == localId);
}
由于Linq懒惰了您的Or
谓词,因此id
仅在执行查询时被评估,并且那时id
的 value 是ids
集合.在这方面foreach
的行为将在C#5中更改,在此不再是问题.有关更多信息,请阅读
Since Linq is lazy your Or
predicate and hence id
will only be evaluated when you execute the query and at that time the value of id
is the last item in the ids
collection. The behavior of foreach
in this regard will be changed in C# 5 where this will not be a problem anymore. For more info read "Closing over the loop variable considered harmful"
这篇关于嵌套或使用Linq PredicateBuilder的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!