Page 1 of 1

linq parameter error

Posted: Wed 22 Jun 2011 13:18
by seser
[keyword = "name surname"]

Code: Select all

var users = db.Users.AsQueryable();
var parts = keyword.Split(new [] {" "}, StringSplitOptions.RemoveEmptyEntries);
foreach (var part in parts)
    users = ordered_users.Where(u => u.UserName.Contains(part) || u.UserSurname.Contains(part));
query in "db monitor"

Code: Select all

SELECT .....
FROM public.users t1
WHERE .... 
AND ((LOWER(t1.user_name) LIKE :p1) OR (LOWER(t1.user_surname) LIKE :p2)) 
AND ((LOWER(t1.user_name) LIKE :p3) OR (LOWER(t1.user_surname) LIKE :p4))
ORDER BY t1.user_id
however parameters likes
[p1 = surname]
[p2 = surname]
[p3 = surname]
[p4 = surname]

while expecting

[p1 = name]
[p2 = name]
[p3 = surname]
[p4 = surname]

Posted: Thu 23 Jun 2011 16:06
by StanislavK
Thank you for the report, we have reproduced the problem. We will post here as soon as it is fixed.

Posted: Wed 06 Jul 2011 14:49
by StanislavK
We've analyzed this issue, it actually comes from the way System.Linq expressions are constructed. Since the lambda expression used as the .Where argument refers to the local variable 'part', the constant value used in the expression changes when 'part' is changed. Thus, the latter value of 'part' should be used for all .Where conditions.

To overcome the problem, you can perform one of the following:
- add both .Where conditions with an explicitly specified element of 'parts':

Code: Select all

users = users.Where(u => u.UserName.Contains(parts[0]) || u.UserSurname.Contains(parts[0]));
users = users.Where(u => u.UserName.Contains(parts[1]) || u.UserSurname.Contains(parts[1]));
- construct the proper expression manually;
- use a recursive method, e.g.

Code: Select all

public IQueryable AddWhere(IQueryable users, string[] parts, int index) {

  if (index  u.UserName.Contains(parts[index]) || u.UserSurname.Contains(parts[index]));
    return AddWhere(users, parts, index + 1);
  }
  else return users;
}
...
users = AddWhere(users, parts, 0);
Please tell us if this helps.