Как добавить динамические предложения where в запрос linq? - PullRequest
25 голосов
/ 08 октября 2008

У меня есть таблица User с битовой маской, которая содержит роли пользователя. Приведенный ниже запрос linq возвращает всех пользователей, роли которых включают 1, 4 или 16.

var users = from u in dc.Users
            where ((u.UserRolesBitmask & 1) == 1)
               || ((u.UserRolesBitmask & 4) == 4)
               || ((u.UserRolesBitmask & 16) == 16)
            select u;

Я хотел бы переписать это в метод ниже, чтобы вернуть всех пользователей с заданными ролями, чтобы я мог использовать его снова:

private List<User> GetUsersFromRoles(uint[] UserRoles) {}

Есть ли какие-нибудь указатели о том, как динамически создавать мой запрос? Спасибо

Ответы [ 6 ]

32 голосов
/ 08 октября 2008

Вы можете использовать класс PredicateBuilder .

PredicateBuilder был выпущен в пакете LINQKit NuGet

LINQKit - это бесплатный набор расширений для опытных пользователей LINQ to SQL и Entity Framework.

3 голосов
/ 08 октября 2008

Вот один из способов добавления переменного числа предложений , где , к вашему запросу LINQ. Обратите внимание, что я не коснулся вашей логики битовой маски, я просто сосредоточился на кратном , где s.

// C#
private List<User> GetUsersFromRoles(uint[] UserRoles)
{
   var users = dc.Users;

   foreach (uint role in UserRoles)
   {
      users = users.Where(u => (u.UserRolesBitmask & role) == role);
   }

   return users.ToList();
}

РЕДАКТИРОВАТЬ: На самом деле, это будет И , где предложения, и вы хотели ИЛИ их. Следующий подход (внутреннее соединение) работает в LINQ to Objects, но не может быть переведен в SQL с LINQ to SQL:

var result = from user in Users
             from role in UserRoles
             where (user.UserRolesBitmask & role) == role
             select user;
3 голосов
/ 08 октября 2008

Есть несколько способов сделать это:

LINQ Динамические библиотеки запросов: http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

Деревья выражений и выражения Lamda: http://msdn.microsoft.com/en-us/library/bb882637.aspx

3 голосов
/ 08 октября 2008

Предполагая, что ваши значения UserRoles сами по себе являются битовыми масками, будет ли что-то подобное работать?

private List<User> GetUsersFromRoles(uint[] UserRoles) {
    uint roleMask = 0;
    for (var i = 0; i < UserRoles.Length;i++) roleMask= roleMask| UserRoles[i];
    // roleMasknow contains the OR'ed bitfields of the roles we're looking for

    return (from u in dc.Users where (u.UserRolesBitmask & roleMask) > 0) select u);
}

Вероятно, есть хороший синтаксис LINQ, который будет работать вместо циклов, но концепция должна быть такой же.

1 голос
/ 08 октября 2008

Как это? Это не динамическое linq, но выполняет цель.

private List<User> GetUsersFromRoles(uint[] userRoles) 
{
    List<User> users = new List<User>();

    foreach(uint userRole in UserRoles)
    {
        List<User> usersInRole = GetUsersFromRole(userRole);
        foreach(User user in usersInRole )
        {
            users.Add(user);
        }
    }
    return users;
}    

private List<User> GetUsersFromRole(uint userRole) 
{
    var users = from u in dc.Users
            where ((u.UserRolesBitmask & UserRole) == UserRole)
            select u;

    return users;    
}
0 голосов
/ 08 октября 2008
private List<User> GetUsersFromRoles(uint UserRoles) {
  return from u in dc.Users            
         where (u.UserRolesBitmask & UserRoles) != 0
         select u;
}

Параметр UserRoles должен быть предоставлен в виде битовой маски, а не массива.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...