Domanda

Ho una tabella utente con una maschera di bit che contiene i ruoli dell'utente. La query linq di seguito restituisce tutti gli utenti i cui ruoli includono 1, 4 o 16.

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

Vorrei riscriverlo nel metodo seguente per restituire tutti gli utenti dai ruoli assegnati in modo da poterlo riutilizzare:

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

Qualche suggerimento su come costruire dinamicamente la mia query? Grazie

È stato utile?

Soluzione

Puoi utilizzare la classe PredicateBuilder .

PredicateBuilder è stato rilasciato nel pacchetto NuQet LINQKit

  

LINQKit è un set gratuito di estensioni per utenti esperti di LINQ to SQL ed Entity Framework.

Altri suggerimenti

Supponendo che i tuoi valori UserRoles siano essi stessi maschere bit, qualcosa del genere funzionerebbe?

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

Probabilmente c'è una bella sintassi LINQ che funzionerà al posto dei loop, ma il concetto dovrebbe essere lo stesso.

Ci sono un paio di modi per farlo:

Librerie di query dinamiche LINQ: http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

Alberi delle espressioni e amp; Espressioni Lamda: http://msdn.microsoft.com/en-us/library/bb882637. aspx

Ecco un modo per aggiungere un numero variabile di dove alla tua query LINQ. Nota che non ho toccato la tua logica di maschera di bit, mi sono solo concentrato sul multiplo dove 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();
}

EDIT: in realtà, questo E le dove clausole e tu le volevi OPPURE . Il seguente approccio (un join interno) funziona in LINQ to Objects ma non può essere tradotto in SQL con LINQ to SQL:

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

Come va? Non è un linq dinamico, ma raggiunge l'obiettivo.

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

Il parametro UserRoles deve essere fornito, tuttavia, come maschera di bit, anziché come matrice.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top