linq parameter error

Discussion of open issues, suggestions and bugs regarding LinqConnect – Devart's LINQ to SQL compatible ORM
Post Reply
seser
Posts: 17
Joined: Thu 13 Jan 2011 20:37

linq parameter error

Post by seser » Wed 22 Jun 2011 13:18

[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]

StanislavK
Devart Team
Posts: 1710
Joined: Thu 03 Dec 2009 10:48

Post by StanislavK » Thu 23 Jun 2011 16:06

Thank you for the report, we have reproduced the problem. We will post here as soon as it is fixed.

StanislavK
Devart Team
Posts: 1710
Joined: Thu 03 Dec 2009 10:48

Post by StanislavK » Wed 06 Jul 2011 14:49

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.

Post Reply