为什么我的目录搜索需要这么长时间?

时间:2017-08-30 05:49:04

标签: c# .net asp.net-web-api directoryservices directorysearcher

我一直在对我构建的REST API中的性能进行故障排除,其中包括根据提供的搜索词从Active Directory返回用户列表。基于我为测试目的而构建的一些日志记录,我可以看到获取设置(例如LDAP搜索信息)和检索所有搜索结果的整个过程只需不到一秒钟:

30/08/2017 3:37:58 PM | Getting search results.
30/08/2017 3:37:58 PM | Retrieving default settings
30/08/2017 3:37:58 PM | Default settings retrieved. Creating directoryEntry
30/08/2017 3:37:58 PM | Search retrieved.
30/08/2017 3:37:58 PM | Iterating through search results.
30/08/2017 3:38:16 PM | Search results iteration complete.

但是,正如您可以看到迭代这些搜索结果并填充我的用户列表需要18秒。这是我的代码:

SearchResultCollection resultList = new DirectorySearcher(CreateDirectoryEntry())
{
    Filter = ("(&(objectClass=user) (cn=*" + SearchTerm + "*))"),
    PropertiesToLoad =
    {
        "givenName",
        "sn",
        "sAMAccountName",
        "mail"
    }
}.FindAll();

foreach (SearchResult result in resultList)
{
    ADUser thisUser = new ADUser();

    try
    {
        thisUser.Firstname = result.Properties["givenName"][0].ToString();
    }
    catch
    {
        thisUser.Firstname = "Firstname not found";
    }
    try
    {
        thisUser.Lastname = result.Properties["sn"][0].ToString();
    }
    catch
    {
        thisUser.Lastname = "Lastname not found";
    }
    try
    {
        thisUser.EmailAddress = result.Properties["mail"][0].ToString();
    }
    catch
    {
        thisUser.EmailAddress = "Email address not found";
    }

    UserList.Add(thisUser);
}

这很香草,没有做任何花哨的事情。知道为什么会这么慢,或者有什么建议我可以做些什么来加快速度呢?

更新

基于评论和答案,我已从代码中删除了空检查。所以现在它看起来像这样:

foreach (SearchResult result in resultList)
{
    ADUser thisUser = new ADUser();

    thisUser.Firstname = result.Properties["givenName"][0].ToString();
    thisUser.Lastname = result.Properties["sn"][0].ToString();
    thisUser.EmailAddress = result.Properties["mail"][0].ToString();

    UserList.Add(thisUser);
}

这并没有改善性能。我可以看到这个循环仍然需要大约18秒,即使只返回一个结果。 (它还证明了我的AD中的蹩脚数据意味着我需要这个空检查!)

2 个答案:

答案 0 :(得分:3)

在设置thisUser的属性时依赖于例外情况,根据您的目录,可能不是例外所有用户都没有givenName的{​​{1}}填充了},sn和/或mail个属性。如果您有一长串搜索结果,则所有这些例外都会累加起来。请考虑检查所需的属性是否存在,而不是使用try / catch块:

thisUser.Firstname = result.Properties.Contains("givenName")
    ? result.Properties["givenName"][0].ToString()
    : "Firstname not found";
thisUser.Lastname = result.Properties.Contains("sn")
    ? result.Properties["sn"][0].ToString()
    : "Lastname not found";
thisUser.EmailAddress = result.Properties.Contains("mail")
    ? result.Properties["mail"][0].ToString()
    : "Email address not found";

您可以使用C {6中的null-conditional operatorsnull-coalescing operator将其简化为以下内容:

thisUser.Firstname = result.Properties["givenName"]?[0]?.ToString() ?? "Firstname not found";
thisUser.Lastname = result.Properties["sn"]?[0]?.ToString() ?? "Lastname not found";
thisUser.EmailAddress = result.Properties["mail"]?[0]?.ToString() ?? "Email address not found";

答案 1 :(得分:1)

你可以尝试这样的事情:

foreach (SearchResult result in resultList)
            {
                ADUser thisUser = new ADUser();
                if(result.Properties["givenName"][0] != null)
                    thisUser.Firstname = result.Properties["givenName"][0].ToString();
                else
                    thisUser.Firstname = "Firstname not found";

                if(thisUser.Lastname = result.Properties["sn"][0] != null)
                    thisUser.Lastname = result.Properties["sn"][0].ToString();
                else
                    thisUser.Lastname = "Lastname not found";

                if(result.Properties["mail"][0] != null)
                    thisUser.EmailAddress = result.Properties["mail"][0].ToString();
                else
                    thisUser.EmailAddress = "Email address not found";

                UserList.Add(thisUser);
            }