tags:

views:

1971

answers:

2

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?

+8  A: 

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:

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));
}
Jon Skeet
Hehe, found this one in the meantime: http://stackoverflow.com/questions/190227/building-a-linq-query-programatically-without-local-variables-tricking-meEasy (but earned) credits to you ;)
borisCallens
pipped me again...
Marc Gravell
+4  A: 

Possibly a captured variable issue; try adding:

List<string> keys = FillKeys()
foreach (string key in keys){
    string tmp = key;
    q = q.Where(c => c.Company.Name.Contains(tmp));
}
Marc Gravell
Thanks. Basically same thing as skeet, but I can only assign one solution. Points though.
borisCallens
No problem. I find it reassuring that we gave the same reply ;-p
Marc Gravell