使用C#中的数据结构算法从Active Directory检索记录

时间:2018-11-26 17:24:03

标签: c# c#-4.0 active-directory binary-tree active-directory-group

我需要获取活动目录记录并插入SQL数据库中。大约有10,000条记录。我使用了以下代码:

List<ADUser> users = new List<ADUser>();

DirectoryEntry entry = new DirectoryEntry("LDAP://xyz.com");
ADUser userToAdd = null;

IList<string> dict = new List<string>();               

DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(&(objectClass=user))";
search.PropertiesToLoad.Add("samaccountname");
search.PageSize = 1000;

foreach (SearchResult result in search.FindAll())
{
    DirectoryEntry user = result.GetDirectoryEntry();

    if (user != null && user.Properties["displayName"].Value!=null)
    {
        userToAdd = new ADUser
                    {
                        FullName = Convert.ToString(user.Properties["displayName"].Value),
                        LanId = Convert.ToString(user.Properties["sAMAccountName"].Value)
                    };

        users.Add(userToAdd);
    }
}

如何在速度和空间复杂度方面优化上述代码?我可以在二叉树中使用遍历,因为Active Directory结构看起来类似于二叉树。

1 个答案:

答案 0 :(得分:0)

DirectorySearcher.FindAll()返回的列表只是一个列表。因此,您无法比以前更好地遍历它。

要对此进行优化,请不要使用GetDirectoryEntry()。这是在做两件事:

  1. 由于搜索可以返回您想要的任何属性,因此不必向AD发出另一个网络请求,并且
  2. 占用内存,因为所有这些DirectoryEntry对象将保留在内存中,直到您调用Dispose()或GC有时间运行(直到循环最终结束为止)。

首先,将displayName添加到您的PropertiesToLoad中,以确保也将其返回。然后,您可以使用result.Properties[propertyName][0]访问每个属性。通过这种方式,每个属性都作为数组返回,即使它是AD中的单值属性,因此也需要[0]

此外,如果此搜索完成后您的应用仍处于打开状态,请确保您从Dispose()出来的SearchResultCollection上调用FindAll()。在FindAll()的文档中,the "Remarks" section表示如果没有,可能会发生内存泄漏。或者,您可以将其放在using块中:

DirectorySearcher search = new DirectorySearcher(entry);
search.Filter = "(&(objectClass=user))";
search.PropertiesToLoad.Add("sAMAccountName");
search.PropertiesToLoad.Add("displayName");
search.PageSize = 1000;
using (SearchResultCollection results = search.FindAll()) {
    foreach (SearchResult result in results) {
        if (result.Properties["displayName"][0] != null) {
            userToAdd = new ADUser {
                FullName = (string) result.Properties["displayName"][0],
                LanId = (string) result.Properties["sAMAccountName"][0]
            };

            users.Add(userToAdd);
        }
    }
}