Лямбда-выражение неверно - PullRequest
       1

Лямбда-выражение неверно

3 голосов
/ 03 августа 2011

Я получаю странные результаты из запроса, который, как мне показалось, я построил правильно.

Этот запрос возвращает 2 значения, что правильно:

int userId = GetUserId(); //Not exactly like this; simplified
var context = new Entities();
//Get the roles 
var relations = (from q in context.UserHasRole
                 where q.UserId == userId
                 select q).ToList();
List<Roles> roles = new List<Roles>();
foreach (var item in relations)
{
    Roles role = (from r in context.Roles
                  where r.Id == item.RoleId
                  select r).SingleOrDefault();
                  roles.Add(role);
 }
 return roles;

Однако этот запрос возвращает 4 значениячто безумно неправильно, так как в БД нет 4 отношений!Возвращает все возможные роли.Для меня запрос выглядит так, как будто он должен возвращать только те записи, в которых отношение имеет как правильный userId, так и roleId.

            //Get the roles 
            var roles = (from q in context.Roles
                         where context.UserHasRole.Any(o => o.UserId == userId)
                         && context.UserHasRole.Any(p => p.RoleId == q.Id)
                         select q).ToList();

            return roles;

Как мне построить лямбда-запрос?

Ответы [ 5 ]

7 голосов
/ 03 августа 2011

Я не делал этого раньше, но я думаю, что вы должны сделать это так:

 //Get the roles 
 var roles = (from q in context.Roles
     where context.UserHasRole.Any(o => o.UserId == userId && o.RoleId == q.Id)
     select q).ToList();

 return roles;
2 голосов
/ 03 августа 2011

Я не могу сказать наверняка, не глядя на ваши данные, но я ожидаю, что ваш запрос вернет вам гораздо больше ролей, чем вы ищете.

Вот псевдокод для существующего запроса:

Get all roles
From those roles, accept only those where these are true:
  Any mapping exists that matches the user ID
  Any mapping exists that matches the role ID

Проблема в том, что вы не гарантируете, что эти пункты Any сводятся к одному и тому же отображению.У пользователя не должно быть этой конкретной роли - у пользователя просто должна быть какая-то роль, и роль должна быть сопоставлена ​​с каким-либо пользователем.

Вот что вы действительно хотите, чтобы ваш запрос выполнял:

Get all roles
From those roles, accept only those where this is true:
  Any mapping exists that matches *both* the user ID and the role ID

Для реализации этого запроса:

var roles = (from r in context.Roles
             where context.UserHasRole.Any(uhr => uhr.UserId == userId
                 && uhr.RoleId == r.Id)
             select r)
            .ToList();
2 голосов
/ 03 августа 2011

Разбейте запрос и посмотрите, что вы делаете на самом деле:

from q in context.Roles

Так что для каждой роли ...

where context.UserHasRole.Any(o => o.UserId == userId)

Там, где существует какая-либо запись в UserHasRole с заданным userId ...

&& context.UserHasRole.Any(p => p.RoleId == q.Id)

И в UserHasRole существует запись с roleId, совпадающим с текущей ролью ...

select q

Выберите эту роль.

У меня такое чувство, что эта логика не та, которую вы хотели, поскольку она независимо проверяет, есть ли запись UserHasRole с идентификатором пользователя и запись UserHasRole с ролью. Но не в том, что есть запись UserHasRole с идентификатором пользователя и ролью, что, вероятно, является желаемым эффектом:

//Get the roles 
var roles = (from q in context.Roles
             where context.UserHasRole.Any(o => o.UserId == userId
                                             && o.RoleId == q.Id)
             select q).ToList();

return roles;
2 голосов
/ 03 августа 2011

Вы запрашиваете роли, в которых «существует связь с конкретным пользователем в таблице UserHasRole» и «существует связь с ролью в таблице UserHasRole».Первое условие будет иметь одинаковый результат для каждой роли, потому что оно не зависит от ролей.

Вам нужны роли, в которых «существует связь между пользователем и роль ".

var roles = (from q in context.Roles
       where context.UserHasRole.Any(o => o.UserId == userId && o.RoleId == q.Id)
       select q).ToList();

return roles;
2 голосов
/ 03 августа 2011

Попробуйте:

var roles = (from q in context.Roles 
   context.UserHasRole.Any(o => 
      o.UserId == userId 
      && o.RoleId == q.Id)
   select q).ToList();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...