如何在linq查询中添加动态“where”子句?

我有一个带有位掩码的User表,其中包含用户的角色。 下面的linq查询返回其角色包括1,4或16的所有用户。

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

我想将其重写为下面的方法,以返回给定角色的所有用户,以便我可以重用它:

 private List GetUsersFromRoles(uint[] UserRoles) {} 

关于如何动态构建我的查询的任何指针? 谢谢

您可以使用PredicateBuilder类。

PredicateBuilder已经在LINQKit NuGet包中发布

LINQKit是LINQ to SQL和Entity Framework高级用户的一组免费扩展。

假设您的UserRoles值本身就是位掩码,那么这样的工作会起作用吗?

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

可能有一个很好的LINQ语法可以代替循环,但概念应该是相同的。

有几种方法可以做到这一点:

LINQ动态查询库: http : //weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

Expression Trees&Lamda表达式: http : //msdn.microsoft.com/en-us/library/bb882637.aspx

这是向LINQ查询添加可变数量的where子句的一种方法。 请注意,我没有触及您的位掩码逻辑,我只关注多个位置 s。

 // C# private List GetUsersFromRoles(uint[] UserRoles) { var users = dc.Users; foreach (uint role in UserRoles) { users = users.Where(u => (u.UserRolesBitmask & role) == role); } return users.ToList(); } 

编辑:实际上,这将ANDwhere子句,你想要他们。 以下方法(内部联接)在LINQ to Objects中有效,但无法使用LINQ to SQL转换为SQL:

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

这个怎么样? 它不是动态的linq,而是实现目标。

 private List GetUsersFromRoles(uint[] userRoles) { List users = new List(); foreach(uint userRole in UserRoles) { List usersInRole = GetUsersFromRole(userRole); foreach(User user in usersInRole ) { users.Add(user); } } return users; } private List GetUsersFromRole(uint userRole) { var users = from u in dc.Users where ((u.UserRolesBitmask & UserRole) == UserRole) select u; return users; } 
 private List GetUsersFromRoles(uint UserRoles) { return from u in dc.Users where (u.UserRolesBitmask & UserRoles) != 0 select u; } 

但是,应提供UserRoles参数作为位掩码,而不是数组。