How do you add dynamic 'where' clauses to a linq query?

后端 未结 6 1044
伪装坚强ぢ
伪装坚强ぢ 2020-12-05 07:19

I\'ve got a User table with a bitmask that contains the user\'s roles. The linq query below returns all the users whose roles include 1, 4 or 16.

var users          


        
相关标签:
6条回答
  • 2020-12-05 07:43

    How's this? It is not dynamic linq, but accomplishes the goal.

    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 讨论(0)
  • 2020-12-05 07:51

    There are a couple of ways you can do this:

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

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

    0 讨论(0)
  • 2020-12-05 07:52

    You can use the PredicateBuilder class.

    PredicateBuilder has been released in the LINQKit NuGet package

    LINQKit is a free set of extensions for LINQ to SQL and Entity Framework power users.

    0 讨论(0)
  • 2020-12-05 07:55
    private List<User> GetUsersFromRoles(uint UserRoles) {
      return from u in dc.Users            
             where (u.UserRolesBitmask & UserRoles) != 0
             select u;
    }
    

    UserRoles parameter should be provided, however, as a bit mask, instead of array.

    0 讨论(0)
  • 2020-12-05 08:01

    Here's one way of adding a variable number of where clauses to your LINQ query. Note that I haven't touched your bitmask logic, I just focused on the multiple wheres.

    // 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: Actually, this will AND the where clauses and you wanted to OR them. The following approach (a inner join) works in LINQ to Objects but can not be translated to SQL with LINQ to SQL:

    var result = from user in Users
                 from role in UserRoles
                 where (user.UserRolesBitmask & role) == role
                 select user;
    
    0 讨论(0)
  • 2020-12-05 08:05

    Assuming your UserRoles values are themselves bitmasks, would something like this work?

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

    There's probably a nice LINQ syntax that'll work in place of the loops, but the concept should be the same.

    0 讨论(0)
提交回复
热议问题