C # Как объединить некоторые выражения Linq в цикле

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);

но когда я совмещаю выражение linq в цикле foreach Как это:

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

Я не могу получить правильный результат (записи) из db.

что такое различие между двумя блоками кода и как решить эту проблему (я должен использовать цикл foreach)?

  • 0
    Вы могли бы что-то сделать с .Where (x => lstPA.Contains (x.post_author)) для того, что, скорее всего, намного быстрее.
  • 2
    Google замыкание над переменной цикла.
Теги:
linq
loops
linq-expressions

3 ответа

7
Лучший ответ

Я считаю, что ваша проблема связана с закрытием. Идентификатор переменной присваивается выражению и он обновляется до нового значения каждый раз, когда вы выполняете цикл. Чтобы использовать его, вы хотите создать индивидуальную переменную с областью.

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);
2

Похож на экземпляр проблемы закрытия foreach. Вы передаете два раза один и тот же идентификатор в базу данных. Примените исправление, описанное в связанном вопросе: Скопируйте id в переменную внутри цикла.

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);
}

это гарантирует, что временная переменная, которая была создана в цикле и никогда не изменена после этого, будет использоваться вместо переменной цикла, которая мутируется во время ее курса.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню