Wie fügt Sie eine linq -Abfrage dynamisch hinzu, wo Klauseln klauseln?
Frage
Ich habe eine Benutzertabelle mit einer Bitmaske, die die Rollen des Benutzers enthält. Die LINQ -Abfrage unten gibt alle Benutzer zurück, deren Rollen 1, 4 oder 16 enthalten sind.
var users = from u in dc.Users
where ((u.UserRolesBitmask & 1) == 1)
|| ((u.UserRolesBitmask & 4) == 4)
|| ((u.UserRolesBitmask & 16) == 16)
select u;
Ich möchte dies in die unten stehende Methode umschreiben, um alle Benutzer aus den angegebenen Rollen zurückzugeben, damit ich sie wiederverwenden kann:
private List<User> GetUsersFromRoles(uint[] UserRoles) {}
Irgendwelche Zeiger, wie ich meine Anfrage dynamisch aufbauen kann? Vielen Dank
Lösung
Du kannst den ... benutzen PredicateBuilder Klasse.
PredicateBuilder wurde in der freigelassen Linqkit Nuget -Paket
Linqkit ist ein kostenloser Satz von Erweiterungen für LINQ zu SQL und Entity Framework Power -Benutzern.
Andere Tipps
Unter der Annahme, dass Ihre Userroles -Werte selbst Bitmäer sind, würde so etwas so funktionieren?
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);
}
Es gibt wahrscheinlich eine schöne Linq -Syntax, die anstelle der Loops funktioniert, aber das Konzept sollte das gleiche sein.
Es gibt ein paar Möglichkeiten, wie Sie dies tun können:
LINQ Dynamic Query Libraries:http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-linq-dynamic-query-library.aspx
Ausdrucksbäume & Lamda -Ausdrücke:http://msdn.microsoft.com/en-us/library/bb882637.aspx
Hier ist eine Möglichkeit, eine variable Anzahl von hinzuzufügen wo Klauseln zu Ihrer Linq -Abfrage. Beachten Sie, dass ich Ihre Bitmaske -Logik nicht berührt habe. Ich habe mich nur auf das Vielfache konzentriert wos.
// 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();
}
Bearbeiten: Eigentlich wird das UND das wo Klauseln und Sie wollten ODER Sie. Der folgende Ansatz (ein innerer Join) funktioniert in LINQ zu Objekten, kann jedoch nicht in SQL mit LINQ in SQL übersetzt werden:
var result = from user in Users
from role in UserRoles
where (user.UserRolesBitmask & role) == role
select user;
Wie ist das? Es ist nicht dynamisch linq, sondern das Ziel.
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;
}
Der Parameter des Userrolen -Parameters sollte jedoch als Bitmaske anstelle von Array bereitgestellt werden.