views:

241

answers:

1

The following C# code (.NET Framework 3.5) returns name and description of all users for an AD Group "xyz". It works great as long as it returns a few number of records. But, it is very slow when it returns more than 100+ records. Any suggestions would be greately appreciated. Thank you in advance!

var context = new PrincipalContext(ContextType.Domain);

var grp = GroupPrincipal.FindByIdentity(context, "xyz");

var users = grp.GetMembers(true);

var usersList = users.Select(n => new { UserName = n.Name, 
                                        Description = n.Description })
                      .OrderBy(o => o.UserName.ToString());

Console.WriteLine(usersList.ToList());
+1  A: 

You will have better performance doing an attribute scope query (ASQ). Here is some example code:

DirectoryEntry group = new DirectoryEntry("LDAP://CN=All Staff,OU=Groups,DC=domain,DC=local");

DirectorySearcher searcher = new DirectorySearcher();
searcher.SearchRoot = group;
searcher.Filter =
   "(&(objectClass=user)(objectCategory=person)(mail=*))";
searcher.PropertiesToLoad.Add("mail");
searcher.SearchScope = SearchScope.Base;

searcher.AttributeScopeQuery = "member";

List<string> mail;
using (SearchResultCollection results = searcher.FindAll())
{
   mail = new List<string>();
   foreach (SearchResult result in results)
   {
        mail.Add(result.Properties["mail"][0].ToString());
   }
}

Generally speaking System.DirectoryServices.AccountManagement is going to give you slower performance than System.DirectoryServices. However 99% of the time you won't be able to notice it. However in this case your example is iterating through each object and pulling it across the wire, while my example is leveraging LDAP to do all the work on our behalf.

Note that this code only works for groups with less than 1000 members. If you have a group larger than that you'll need to page which is more complicated code but not a big deal.

Steve Evans
Thank you so much! I noticed improved performance when I changed the grp.GetMembers(true) to grp.GetMembers(false). My code also returned all rows instead of first 1000.
rk1962