1

複数のエントリを返し、それらをSearchResultCollection内に格納するLDAPクエリを実行しています。私は次のようにSearchResultCollectionを繰り返し処理しています。

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

これはこれを行うための最も論理的な方法のように思えますが、ループは非常に遅いです。デバッガーを使用してループをステップスルーすると、時間がかかるforeachループを初期化する最初のステップであることがわかります。実際の反復は瞬時に行われます。

さらに、デバッグ中にSearchResultCollectionのコンテンツを表示すると、ウォッチが変数のコンテンツをロードするのと同じくらいの時間がかかります。

SearchResultCollectionには実際には完全なSearchResultオブジェクトが含まれているのではなく、SearchResultCollectionオブジェクトを反復処理するときに個別にフェッチされるActiveDirectoryサーバーのエントリへの参照が含まれているという理論があります。誰かがこの理論を確認できますか?そして、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()

...これはパフォーマンスに劇的な影響を及ぼします。ループ内のディクショナリにコレクションを追加してからディクショナリを処理することで、これを回避できます。

    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

ディクショナリonyには2つのエントリがあるため、少し制限がありますが、他の値をコンマで区切るか、ディクショナリ内の値のディクショナリを使用できます。

    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

応答時間を短縮する方法はいくつかあります。

  • 検索範囲を制限する
  • より制限の厳しい検索フィルターを使用する
  • 取得するオブジェクトに近いベースオブジェクトを使用します。

も参照してください

于 2012-06-04T21:43:32.067 に答える