Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linq query built in foreach loop always takes parameter value from last iteration

Tags:

c#

linq

I have a List containing several keywords. I foreach through them building my linq query with them like so (boiled down to remove the code noise):

List<string> keys = FillKeys()
foreach (string key in keys){
    q = q.Where(c => c.Company.Name.Contains(key));
}

When I now make my keys contain 2 keys that return results seperatly, but can never occure together (every item in q is either "xyz" or "123", never "123" AND "xyz"), I still get results. The resultset is then the same as the last string it got to.

I had a look at the linq query and it appears it creates the correct sql, but it replaces @p1 AND @p2 both by the same (last itterated) value.

What am I doing wrong?

like image 442
Boris Callens Avatar asked Nov 17 '08 13:11

Boris Callens


People also ask

Is LINQ query faster than foreach?

No, LINQ iterators are not and will never be faster than foreach .

How do you get the index of the current iteration of a foreach loop?

C# Program to Get the index of the Current Iteration of a foreach Loop Using Select() Method. The method Select() is a LINQ method. LINQ is a part of C# that is used to access different databases and data sources. The Select() method selects the value and index of the iteration of a foreach loop.

Does foreach have an index?

C#'s foreach loop makes it easy to process a collection: there's no index variable, condition, or code to update the loop variable. Instead the loop variable is automatically set to the value of each element. That also means that there's no index variable with foreach .

Is LINQ slower than for loop?

Yes, it's slower.


1 Answers

You're reusing the same variable (key) in your lambda expression.

See my article on anonymous methods for more details, and there are a number of related SO questions too:

  • LINQ to SQL bug (or very strange feature)...
  • Local variables with delegates
  • C# captured variable in a loop
  • C# gotcha answer
  • Building a LINQ query programmatically without local variables tricking me

The simple fix is to copy the variable first:

List<string> keys = FillKeys()
foreach (string key in keys){
    string copy = key;
    q = q.Where(c => c.Company.Name.Contains(copy));
}
like image 120
Jon Skeet Avatar answered Sep 21 '22 11:09

Jon Skeet