Search code examples
c#linqasp.net-membershipuser-roles

Better method to get users belonging to no role?


I wrote the following that does work, but want to know if there is any more efficient ways to get all users without any role.

using System.Collections.Generic;
using System.Linq;
using System.Web.Security;

public static IEnumerable<MembershipUser> GetUsersHavingNoRole() {
  var allUsers = Membership.GetAllUsers().Cast<MembershipUser>();
  foreach (var user in allUsers) {
    if (Roles.GetRolesForUser(user.UserName).Length.Equals(0)) {
      yield return user;
    }
  }
}

Solution

  • I'd expect there to usually be more users than roles - so it might make sense to iterate over the roles (return by Roles.GetAllRoles()), build up a list of users in any of those roles (e.g. by creating a HashSet<string> and adding the users for each role returned by Roles.GetUsersInRole), and then finding the difference between that and all the users. So if you're using LINQ, you could use:

    var usersInRolesQuery = Roles.GetAllRoles()
                                 .SelectMany(role => Roles.GetUsersInRole(role));
    
    var usersInRoles = new HashSet<string>(usersInRolesQuery);
    return Membership.GetAllUsers()
                     .Cast<MembershipUser>()
                     .Where(user => !usersInRoles.Contains(user.UserName));
    

    Of course that's still dealing with the same amount of data - but it may mean fewer roundtrips to whatever datastore is involved.

    Have you benchmarked the application to find out how expensive your current method is?