1

我想结合一些 Linq 表达式,所以我从下面的文章中得到帮助:

http://www.c-sharpcorner.com/uploadfile/04fe4a/predicate-combinators-in-linq/http://thanhhh.blogspot.com/2011/10/linq-to-entities-predicatebuilder-and.html

我有一个这样的通用列表:

List<long> lstPA = new List<long>() { 2, 3 }; // the numbers can be added or removed

如果我在代码下使用组合我的 linq 表达式,我会从 db 获得正确的结果(记录)(我使用 Entity Framework 4.0):

var exp1 = Predicate.FalseExpression<posts>();            
exp1 = exp1.Or(x => x.post_author == 2);
exp1 = exp1.Or(x => x.post_author == 3);

但是当我在 foreach 循环中结合 linq 表达式时,像这样:

var exp1 = Predicate.FalseExpression<posts>();
foreach (long id in lstPA)
{
    exp1 = exp1.Or(x => x.post_author == id);
}

我无法从 db 获得正确的结果(记录)。

2个代码块之间有什么区别以及如何解决这个问题(我必须使用foreach循环)?

4

3 回答 3

7

我相信您的问题与关闭有关。变量 id 分配给表达式,每次循环时它都会更新为更新的值。为了使用它,您需要创建一个单独作用域的变量。

var exp1 = Predicate.FalseExpression<posts>();
foreach (long i in lstPA)
{
    long id = i;
    exp1 = exp1.Or(x => x.post_author == id);
}

但是,在这种情况下,您可以只使用 contains 子句。

expr1 = x => lstPA.Contains(x.post_author);
于 2014-07-25T11:22:15.260 回答
2

看起来像 foreach 闭包问题的一个实例。您将两次相同的 ID 传递给数据库。应用链接问题中描述的修复:复制id到循环内的变量。

于 2014-07-25T11:21:51.070 回答
1

在我看来,这似乎是闭包和循环的问题。Id 引用循环变量并将继续这样做,这意味着它会更改并读取类似的内容

exp1 = exp1.Or(x => x.post_author == 3);
exp1 = exp1.Or(x => x.post_author == 3);

展开时。要解决此问题,您可以尝试:

var exp1 = Predicate.FalseExpression<posts>();
foreach (long id in lstPA)
{
  long tempID = id;
  exp1 = exp1.Or(x => x.post_author == tempID);
}

这可以确保使用在循环中创建并且之后从未更改过的临时变量,而不是在其过程中发生突变的循环变量。

于 2014-07-25T11:28:09.920 回答