1

我正在运行一个 LDAP 查询,它返回多个条目并将它们存储在 SearchResultCollection 中。我正在迭代 SearchResultCollection,如下所示:

// results is my SearchResultCollection object
foreach (SearchResult sr in results)  
{
    ... do things to each SearchResult in here ...
}

这似乎是最合乎逻辑的方法,但循环非常慢。当我使用调试器单步执行循环时,我发现这是初始化 foreach 循环的第一步需要时间——实际的迭代是瞬时的。

此外,当我在调试时查看 SearchResultCollection 的内容时,手表加载变量内容的时间也一样长。

我有一个理论,即 SearchResultCollection 实际上并不包含完整的 SearchResult 对象,而是对 Active Directory 服务器中的条目的引用,然后在我遍历 SearchResultCollection 对象时单独获取这些条目。谁能证实这个理论?是否有更好(更快)的方法来获取一组 LDAP 条目?

4

3 回答 3

2

我遇到了同样的问题,下面帖子中的方法比我自己的要快得多:

http://msdn.microsoft.com/en-us/library/ms180881(v=vs.80).aspx

...要回答您的问题,是的,好像您尝试在仍在循环中时直接使用以下内容处理条目:

     If Not UserAccount.GetDirectoryEntry().Properties("sAMAccountName").Value Is Nothing Then sAMAccountName = UserAccount.Properties("sAMAccountName")(0).ToString()

...这对性能有很大影响,您可以通过将集合添加到循环内的 Dictionary 然后处理字典来解决此问题:

    Dim searchResult As SearchResult
    Dim dictLatestLogonDatesTemp As New Dictionary(Of String, Date)
    SearchResults1 = mySearcher.FindAll()
    For Each searchResult In SearchResults1
        Dim propertyKey,sAMAccountName  As String
        Dim dteLastLogonDate As Date = Nothing
        For Each propertyKey In searchResult.Properties.PropertyNames
            Dim valueCollection As ResultPropertyValueCollection = searchResult.Properties(propertyKey)
            For Each propertyValue As Object In valueCollection
                If LCase(propertyKey) = LCase("sAMAccountName") Then sAMAccountName = propertyValue
                If LCase(propertyKey) = LCase("lastLogon") Then dteLastLogonDate = Date.FromFileTime(propertyValue)
            Next propertyValue
        Next propertyKey
        If sAMAccountName <> Nothing Then dictLatestLogonDatesTemp.Add(sAMAccountName, dteLastLogonDate)
    Next searchResult

这有点限制,因为字典只有两个条目,但您可以用逗号分隔其他值或使用字典中的值字典:

    Dim tempDictionary As Dictionary(Of String, Dictionary(Of String, String))

希望这对某人有帮助!

于 2012-07-17T14:47:01.250 回答
0

我想提交的是,将它们添加到数据表也非常有效,并且允许比字典更多的属性。我从在 searchresultscollection 中迭代 2000 个用户花费了将近 2 分钟到不到 1-2 秒。希望这对其他人有帮助。

  Private Sub getAllUsers()
    Dim r As SearchResultCollection
    Dim de As DirectoryEntry = New DirectoryEntry(GetCurrentDomainPath)
    Dim ds As New DirectorySearcher(de)

    ds.SearchScope = SearchScope.Subtree
    ds.PropertiesToLoad.Add("name")
    ds.PropertiesToLoad.Add("distinguishedName")
    ds.PropertiesToLoad.Add("objectSID")
    ds.Filter = "(&(objectCategory=person)(objectClass=user))" '(!userAccountControl:1.2.840.113556.1.4.803:=2) not disabled users 

    PleaseWait.Status("Loading Users...")
    Application.DoEvents()

    r = ds.FindAll()

    Dim dt As New DataTable
    dt.Columns.Add("Name")
    dt.Columns.Add("SID")

    For Each sr As SearchResult In r
        Dim SID As New SecurityIdentifier(CType(sr.Properties("objectSID")(0), Byte()), 0)
        dt.Rows.Add(sr.Properties("name")(0).ToString(), SID.ToString)
    Next

    With lstResults
        lstResults.DataSource = dt
        .DisplayMember = "name"
        .ValueMember = "SID"
        .Items.Sort()
    End With

End Sub
于 2020-08-17T21:17:05.107 回答
-2

There may be some ways to decrease the response time:

  • restrict the scope of the search
  • use a more restrictive search filter
  • use a base object closer to the object(s) being retrieved.

see also

于 2012-06-04T21:43:32.067 回答