2

したがって、基本的にADからの結果を列挙しようとしていますが、何らかの理由で新しい結果を取得できません。つまり、追加の範囲が必要だと言っても、最初の1500件の結果を継続的に取得し続けます。

誰かが私が間違いを犯している場所を指摘できますか?コードがループから抜け出すことはありませんが、さらに重要なことに、ユーザーに1500〜3000が必要だと言っても、ユーザーを1〜1500にプルします。

uint rangeStep = 1500;   
uint rangeLow = 0;   
uint rangeHigh = rangeLow + (rangeStep - 1);   
bool lastQuery = false;   
bool quitLoop = false;   

do   
{                       
    string attributeWithRange;   
    if (!lastQuery)   
    {   
        attributeWithRange = String.Format("member;Range={0}-{1}", rangeLow, rangeHigh);   
    }   
    else   
    {   
        attributeWithRange = String.Format("member;Range={0}-*", rangeLow);   
    }   
    DirectoryEntry dEntryhighlevel = new DirectoryEntry("LDAP://OU=C,OU=x,DC=h,DC=nt");   
    DirectorySearcher dSeacher = new DirectorySearcher(dEntryhighlevel,"(&(objectClass=user)(memberof=CN=Users,OU=t,OU=s,OU=x,DC=h,DC=nt))",new string[] {attributeWithRange});   
    dSeacher.PropertiesToLoad.Add("givenname");   
    dSeacher.PropertiesToLoad.Add("sn");   
    dSeacher.PropertiesToLoad.Add("samAccountName");   
    dSeacher.PropertiesToLoad.Add("mail");   
    dSeacher.PageSize = 1500;   
    SearchResultCollection resultCollection = resultCollection = dSeacher.FindAll();   
    dSeacher.Dispose();   

    foreach (SearchResult userResults in resultCollection)   
    {   

        string Last_Name = userResults.Properties["sn"][0].ToString();   
        string First_Name = userResults.Properties["givenname"][0].ToString();   
        string userName = userResults.Properties["samAccountName"][0].ToString();   
        string Email_Address = userResults.Properties["mail"][0].ToString();   
        OriginalList.Add(Last_Name + "|" + First_Name + "|" + userName + "|" + Email_Address);   
    }   
    if(resultCollection.Count == 1500)   
    {   
        lastQuery = true;   
        rangeLow = rangeHigh + 1;   
        rangeHigh = rangeLow + (rangeStep - 1);   
    }   
    else   
    {   
        quitLoop = true;   
    }   

}   
while (!quitLoop);
4

2 に答える 2

1

問題の原因となっている 2 つの概念を混同しています。これは SO フォーラムの FAQ であるため、問題を解決するためにブログに投稿する必要があります。

最初に概念を説明し、概念が明らかになったらコードを修正します。

コンセプト 1 は、オブジェクトの大規模なコレクションをフェッチすることです。大量のオブジェクトをフェッチするときは、それらをバッチで要求する必要があります。これは通常、結果の「ページング」と呼ばれます。これを行うと、ページング Cookie が返され、その後の検索でページ コントロールを返して、各パスで「ページに相当する」結果を取得し続けることができます。

2 番目の概念は、1 つの属性から多数の値をフェッチすることです。この簡単な例は、グループからメンバー属性を読み取ることです (例: そのグループのベース検索を行う)。これを「遠隔回収」と呼びます。この検索モードでは、そのオブジェクトに対して大きな属性 (メンバーなど) の基本検索を実行し、検索を通過するたびに値の「範囲」を要求します。

上記のコードは、これらの概念を混同しています。範囲検索を行うようにメンバー範囲ロジックを実行していますが、実際には、ページ検索のように多数のオブジェクトを返すように構築された検索を実行しています。これが、同じ結果が何度も得られる理由です。

これを修正するには、まずアプローチを選択する必要があります。:) グループ オブジェクトに対して範囲検索を行い、範囲内の大きなメンバー属性を要求することをお勧めします。これにより、グループ内のすべてのメンバーが取得されます。この道をたどると、これらの値の属性を要求できないことがわかります。取得できる唯一の値はメンバーのリストであり、その後でそれらを検索できます。上記のようにページ検索にとどまることを選択した場合、ページ検索に切り替えることになります。

ページ検索に固執することを選択した場合は、次のことを行う必要があります。

  • Range ロジックと 1500 のすべての言及を取り除きます
  • 1000 のようなページ サイズを設定します。
  • 範囲を広げる代わりに、API を使用して (ページ検索コントロールを使用して) ページ検索を行う方法を調べます。

レンジングを選択すると、次のような memberOf 検索から次の形式の検索に切り替わります: a) スコープ: ベース b) フィルター: (objectclass= ) c) ベース DN: OU=C,OU=x,DC= h,DC=nt d) 属性: member;Range=0- ...次に、値の範囲をフェッチするときに 0 をインクリメントします (つまり、この検索を後続の値の範囲ごとに何度も繰り返します。 0 から後続の整数) 私のロジックで気付くその他の点: - ページ サイズを設定していません... ページ検索を行っていないため、問題ありません。- ここで値 1500 をハードコーディングすることはありません。それは問題ではありません。これを知っていても、計算しても何の価値もありません。ポイントは、0-* (つまりすべて) を要求したところ、1500 が返されたので、1500- と言い、次に 3000-と言うということです。、 等々。範囲のサイズを知る必要はありません。これまでに与えられたものだけです。

これが完全に答えてくれることを願っています...

以下の私のコメントによると、ページ検索を実行するコードの一部を次に示します (これは、System.DirectoryServices.Protocols 名前空間クラスを使用して、上で開始した論理パスをたどる必要があることです (ページ検索、範囲検索ではありません)。 ):

        string searchFilter = "(&(objectClass=user)(memberof=CN=Users,OU=t,OU=s,OU=x,DC=h,DC=nt))";
        string baseDN = "OU=C,OU=x,DC=h,DC=nt";
        var scope = SearchScope.Subtree;
        var attributeList = new string[] { "givenname", "sn", "samAccountName", "mail" };
        PageResultRequestControl pageSearchControl = new PageResultRequestControl(1000);
        do
        {
            SearchRequest sr = new SearchRequest(baseDN, searchFilter, scope, attributeList);
            sr.Controls.Add(pageSearchControl);

            var directoryResponse = ldapConnection.SendRequest(sr);
            if (directoryResponse.ResultCode != ResultCode.Success)
            {
                // Handle error
            }

            var searchResponse = (SearchResponse)directoryResponse;

            pageSearchControl = null; // Reset!
            foreach (var control in searchResponse.Controls)
            {
                if (control is PageResultResponseControl)
                {
                    var prrc = (PageResultResponseControl)control;
                    if (prrc.Cookie.Length > 0)
                    {
                        pageSearchControl = new PageResultRequestControl(prrc.Cookie);
                    }
                }
            }

            foreach (var entry in searchResponse.Entries)
            {
                // Handle the search result entry
            }
        } while (pageSearchControl != null);
于 2012-09-05T04:23:24.020 に答える
-1

あなたの問題は、ディレクトリサーチャーの新しいオブジェクトをループで作成することが原因です。最初の 1500 レコードを取得する新しいオブジェクトが存在するたびに。ループから検索者のインスタンスを作成し、すべてのクエリに同じインスタンスを使用します。

于 2012-09-04T21:05:56.100 に答える