2008-10-07 14 views
23

Ho una tabella utente con una maschera di bit che contiene i ruoli dell'utente. La query LINQ seguito restituisce tutti gli utenti i cui ruoli includono 1, 4 o 16.Come si aggiungono clausole 'where' dinamiche a una query linq?

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

mi piacerebbe riscrivere questo nel metodo seguito per rendimenti tutti gli utenti dai ruoli dato così posso riutilizzare esso:

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

Eventuali puntatori su come creare dinamicamente la mia query? Grazie

risposta

31

È possibile utilizzare la classe PredicateBuilder.

PredicateBuilder è stato rilasciato nel LINQKit NuGet package

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

+3

Apparentemente la classe PredicateBuilder è disponibile in due versioni: l'esempio del codice sorgente sul sito Web, che è © Albahari & O'Reilly, tutti i diritti riservati; e come parte di LinqKit, che è "sotto una licenza gratuita permissiva, il che significa che è possibile modificarlo a piacimento e incorporarlo nel proprio software commerciale o non commerciale". – Sjoerd

+0

LinqKit è disponibile tramite NuGet. –

2

Supponendo che i valori UserRoles siano essi stessi maschere di bit, sarebbe qualcosa di simile a questo lavoro?

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

C'è probabilmente un bel sintassi LINQ che lavorerò al posto delle anse, ma il concetto dovrebbe essere lo stesso.

+0

Questo dovrebbe funzionare. Invece della clausola dynamic where l'hai ridotta a una singola. E la bella sintassi LINQ che hai citato potrebbe essere: uint roleMask = UserRoles.Aggregate (0, (combinato, ruolo) => combinato | ruolo); – Lucas

1

Come va? Non è 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;  
} 
+0

utenti.AddRange (usersInRole); –

+0

Inoltre, è necessario ToList in GetUsersFromRole –

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

UserRoles parametri dovrebbe essere fornito, tuttavia, come una maschera di bit, invece di array.

+0

Ciò restituirà gli utenti che corrispondono a TUTTI i ruoli specificati. Il suo metodo restituisce utenti che corrispondono a QUALSIASI ruolo assegnato. – Lucas

3

Ecco un modo di aggiungere un numero variabile di dove clausole per la query LINQ. Nota che non ho ancora toccato la tua logica di maschera di bit, mi sono 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 sarà E le dove clausole e si voleva o. Il seguente approccio (un inner join) funziona in LINQ to Objects ma non può essere tradotto in SQL con LINQ to SQL:

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