Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

getting user details from AD is slow

Im using the following code to get a bunch of information about employees from specific departments and returning a list from AD...

Whilst it works, it appears to be quite slow, is a there more efficient way of getting various user details from AD?

public static List<Employee> GetEmployeeListForDepartment(string departpment)
        {
            using (HostingEnvironment.Impersonate())
            {

                PrincipalContext ctx = new PrincipalContext(ContextType.Domain, domain);
                GroupPrincipal gp = GroupPrincipal.FindByIdentity(ctx, departpment);
                PrincipalSearchResult<Principal> members = gp.GetMembers();
                List<Employee> employees = new List<Employee>();
                foreach (var member in members)
                {
                    var emp = CreateEmployee(member);
                    employees.Add(emp);
                }
                return employees.OrderBy(x => x.FirstName).ToList();
            }
        }

        private static Employee CreateEmployee(Principal member)
        {
            if (member != null)
            {
                DirectoryEntry de = (member.GetUnderlyingObject() as DirectoryEntry);
                if (de != null)
                {

                    string mobile = de.Properties.Contains("mobile") ? de.Properties["mobile"][0].ToString() : "";
                    string title = de.Properties.Contains("description") ? de.Properties["description"][0].ToString() : "";

//ETC ETC...
                    return new Employee { etc.. };

                }

            }
            return new Employee();
        }
like image 681
raklos Avatar asked Oct 31 '11 15:10

raklos


1 Answers

Your problem is that you are using System.DirectoryServices.AccountManagement... While I hate saying it, it's sadly the truth. The way AccountManagement works under the hood is that it runs a seperate LDAP query to retrieve each item seperately. So when you iterate through members it's making a seperate call back through LDAP for each member. What you want to do instead is run an LDAP query using System.DirectoryServices.DirectorySearcher.

My assumption is that department is a group, based on how you are using it. Here is how I would do it. (my code is in VB.Net... sorry). Make sure to get the fully qualified DN for your group, or look it up in advance and plug it into the query.

Dim results = LDAPQuery("(memberOf=CN=Fully,OU=Qualified,DC=Group,DC=Distinguished,DC=Name)", New String() {"mobile", "description"})

Dim emps = (from c as System.DirectoryServices.SearchResult in results _
             Select New Employee() {.Name = c.Properties("description"), .Mobile = c.Properties("mobile")}).ToList()

Public Function LDAPQuery(ByVal query As String, ByVal attributes As String()) As SearchResultCollection
    'create directory searcher from CurrentADContext (no special security available)
    Dim ds As New DirectorySearcher(System.DirectoryServices.ActiveDirectory.Domain.GetCurrentDomain().GetDirectoryEntry())
    ds.PageSize = 1000

    'set filter string
    ds.Filter = query

    'specify properties to retrieve
    ds.PropertiesToLoad.AddRange(attributes)

    'get results
    Dim results As SearchResultCollection = ds.FindAll()

    Return results
End Function
like image 155
Peter Avatar answered Oct 26 '22 17:10

Peter