Подтвердить что ты не робот

Как добавить динамические предложения "where" к запросу linq?

У меня есть таблица 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) {}

Любые указатели на то, как динамически строить мой запрос? Благодаря

4b9b3361

Ответ 1

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

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

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

Ответ 3

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

// 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();
}

EDIT: на самом деле это будет И предложения where, и вы хотели бы ИЛИ их. Следующий подход (внутреннее соединение) работает в LINQ для объектов, но не может быть переведен на SQL с LINQ to SQL:

var result = from u in Users
             from role in UserRoles
             where (u.UserRolesBitmask & role) == role)
             select u;

Ответ 4

Предполагая, что ваши значения 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, который будет работать вместо циклов, но концепция должна быть одинаковой.

Ответ 5

Как это? Это не динамический 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;    
}

Ответ 6

private List<User> GetUsersFromRoles(uint UserRoles) {
  return from u in dc.Users            
         where (u.UserRolesBitmask & UserRoles) != 0
         select u;
}

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