2

I am using Linq and the Entity Framework. I have a Page Entity, that has a many-to-many relationship to a Tag Entity.

I want to create a Linq query that pulls all pages that match all of the supplied Tags (in the form of a Int64[]).

I have tried various WhereIn, and BuildContainsExpression examples, but none are working as expected.

I am now trying to loop through each of the Tags and build a list of expressions:

 foreach (Int64 item in Tags)
 {
    Expression<Func<Pages, bool>> tagFilter = c => c.Tags.Any(x => x.TagID == item);
    exp.Add(tagFilter);
 }

However, I think the local variable "item" is messing with the query because it either is using one tag, or none of them when the query runs, however if I specify them like this:

 Expression<Func<Pages, bool>> tagFilter1 = c1 => c1.Tags.Any(x => x.TagID == 70);
 exp.Add(tagFilter1);
 Expression<Func<Pages, bool>> tagFilter2 = c1 => c1.Tags.Any(x => x.TagID == 130);
 exp.Add(tagFilter2);
 Expression<Func<Pages, bool>> tagFilter3 = c1 => c1.Tags.Any(x => x.TagID == 77);
 exp.Add(tagFilter3);

Using the actual number "70" for example, it works like a charm. I am basically storing the expressions in a list and using LinqKit to And() them.

Is there a way to keep this dynamic?

Ryan M
  • 605
  • 1
  • 8
  • 17

1 Answers1

4

Change your code to:

foreach (Int64 item in Tags)
{
    var temp = item; // this variable is scoped **inside** the loop.
    Expression<Func<Pages, bool>> tagFilter = c => c.Tags.Any(x => x.TagID == temp);
    exp.Add(tagFilter);
}

For a detailed explanation, read my answer to the "What is the exact definition of a closure?" question.

Community
  • 1
  • 1
Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
  • It seems that everyone runs into this problem at least once when working with lambdas. They should really look into making it a compiler warning to use a variable scoped in a foreach/for directly in a lambda. – bobbymcr Aug 31 '09 at 00:41