2008-10-07 22 views
23

Tengo una tabla de usuario con una máscara de bits que contiene las funciones del usuario. La consulta LINQ siguiente restituye todos los usuarios cuyas funciones incluyen 1, 4 ó 16.¿Cómo se agregan las cláusulas dinámicas 'where' a una consulta linq?

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

me gustaría volver a escribir esto en el método siguiente para todos los usuarios rendimientos de los papeles dados por lo que puede volver a utilizarla:

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

¿Alguna sugerencia sobre cómo construir dinámicamente mi consulta? Gracias

Respuesta

31

Puede usar la clase PredicateBuilder.

PredicateBuilder ha sido puesto en libertad en el LINQKit LINQKit NuGet package

es un conjunto gratuito de extensiones para LINQ a SQL y usuarios avanzados de Entity Framework.

+3

Aparentemente la clase PredicateBuilder está disponible en dos versiones: el ejemplo del código fuente en el sitio web, que es © Albahari & O'Reilly, todos los derechos reservados; y como parte de LinqKit, que se encuentra "bajo una licencia libre permisiva, lo que significa que puede modificarlo como lo desee e incorporarlo en su propio software comercial o no comercial". – Sjoerd

+0

LinqKit está disponible a través de NuGet. –

2

Suponiendo que los valores de UserRoles son ellos mismos máscaras de bits, ¿funcionaría algo así?

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

Probablemente hay una sintaxis LINQ agradable que va a trabajar en el lugar de los bucles, pero el concepto debería ser el mismo.

+0

Esto debería funcionar. En lugar de la cláusula dynamic where, la redujo a una sola. Y esa buena sintaxis de LINQ que mencionó podría ser: uint roleMask = UserRoles.Aggregate (0, (combinado, rol) => combinado | rol); – Lucas

1

¿Cómo es esto? No es dinámico, pero cumple el 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;  
} 
+0

usuarios.AddRange (usersInRole); –

+0

Además, necesita ToList en GetUsersFromRole –

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

UserRoles parámetros debe proporcionarse, sin embargo, como una máscara de bits, en lugar de array

+0

Esto devolverá los usuarios que coinciden con TODAS las funciones dadas. Su método devuelve usuarios que coinciden con CUALQUIERA de los roles dados. – Lucas

3

He aquí una manera de añadir un número variable de donde cláusulas a su consulta LINQ. Tenga en cuenta que no he tocado su lógica de máscara de bits, solo me concentré en el múltiple donde 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: En realidad, esto Y los donde cláusulas y que quería O ellos. El siguiente enfoque (una unión interna) funciona en LINQ to Objects pero no se puede traducir a SQL con LINQ to SQL:

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