Pergunta

Eu tenho uma tabela de usuários com uma máscara de bits que contém as funções do usuário. A consulta LINQ abaixo retorna todos os usuários cujas funções incluem 1, 4 ou 16.

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

Eu gostaria de reescrever isso no método abaixo para retornar todos os usuários das funções dadas para que eu possa reutilizá -lo:

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

Algum indicador sobre como criar minha consulta dinamicamente? Obrigado

Foi útil?

Solução

Você pode usar o PredicateBuilder classe.

PredicateBuilder foi lançado no Pacote linqkit nuget

O Linqkit é um conjunto gratuito de extensões para os usuários do LINQ para SQL e Entity Framework.

Outras dicas

Supondo que seus valores de UserRoles sejam mesmas máscaras de bits, algo como esse funcionaria?

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

Provavelmente há uma sintaxe LINQ agradável que funcionará no lugar dos loops, mas o conceito deve ser o mesmo.

Existem algumas maneiras de fazer isso:

Bibliotecas de consulta dinâmica Linq:http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

Expressão árvores e expressões Lamda:http://msdn.microsoft.com/en-us/library/bb882637.aspx

Aqui está uma maneira de adicionar um número variável de Onde Cláusulas para sua consulta LINQ. Observe que não toquei na sua lógica de máscara de bits, acabei de me concentrar no múltiplo Ondes.

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

Editar: na verdade, isso vai E a Onde cláusulas e você queria OU eles. A abordagem a seguir (uma junção interna) trabalha no LINQ para objetos, mas não pode ser traduzida para SQL com LINQ para SQL:

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

Como é isso? Não é o LINQ dinâmico, mas atinge o objetivo.

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

O parâmetro userroles deve ser fornecido, no entanto, como uma máscara de bits, em vez de matriz.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top