Kann ich mehr als 1000 Datensätze von einem DirectorySearcher abrufen?

72

Ich habe gerade festgestellt, dass die Rückgabeliste für Ergebnisse auf 1000 beschränkt ist. Ich habe mehr als 1000 Gruppen in meiner Domain (RIESIGE Domain). Wie kann ich mehr als 1000 Datensätze erhalten? Kann ich mit einer späteren Aufnahme beginnen? Kann ich es in mehrere Suchanfragen aufteilen?

Hier ist meine Frage:

DirectoryEntry dirEnt = new DirectoryEntry("LDAP://dhuba1kwtn004");
string[] loadProps = new string[] { "cn", "samaccountname", "name", "distinguishedname" };
DirectorySearcher srch = new DirectorySearcher(dirEnt, "(objectClass=Group)", loadProps);
var results = srch.FindAll();

Ich habe versucht, srch.SizeLimit = 2000 zu setzen; , aber das scheint nicht zu funktionieren. Irgendwelche Ideen?

naspinski
quelle

Antworten:

180

Sie müssen DirectorySearcher.PageSize auf einen Wert ungleich Null setzen, um alle Ergebnisse zu erhalten.

Übrigens sollten Sie DirectorySearcher auch entsorgen, wenn Sie damit fertig sind

using(var srch = new DirectorySearcher(dirEnt, "(objectClass=Group)", loadProps))
{
    srch.PageSize = 1000;
    var results = srch.FindAll();
}

Die API-Dokumentation ist nicht sehr klar, aber im Wesentlichen:

  • Wenn Sie eine ausgelagerte Suche durchführen, wird das SizeLimit ignoriert und alle übereinstimmenden Ergebnisse werden zurückgegeben, während Sie die von FindAll zurückgegebenen Ergebnisse durchlaufen. Die Ergebnisse werden seitenweise vom Server abgerufen. Ich habe oben den Wert 1000 gewählt, aber Sie können einen kleineren Wert verwenden, wenn Sie dies bevorzugen. Der Nachteil ist: Die Verwendung einer kleinen PageSize gibt jede Ergebnisseite schneller zurück, erfordert jedoch häufigere Aufrufe des Servers, wenn über eine große Anzahl von Ergebnissen iteriert wird.

  • Standardmäßig wird die Suche nicht ausgelagert (PageSize = 0). In diesem Fall werden bis zu SizeLimit-Ergebnisse zurückgegeben.

Wie Biri betonte, ist es wichtig, die von FindAll zurückgegebene SearchResultCollection zu entsorgen, da sonst möglicherweise ein Speicherverlust auftritt, wie im Abschnitt "Anmerkungen" der MSDN-Dokumentation für DirectorySearcher.FindAll beschrieben .

Eine Möglichkeit, dies in .NET 2.0 oder höher zu vermeiden, besteht darin, eine Wrapper-Methode zu schreiben, die die SearchResultCollection automatisch verfügbar macht. Dies könnte ungefähr so ​​aussehen (oder eine Erweiterungsmethode in .NET 3.5 sein):

public IEnumerable<SearchResult> SafeFindAll(DirectorySearcher searcher)
{
    using(SearchResultCollection results = searcher.FindAll())
    {
        foreach (SearchResult result in results)
        {
            yield return result;        
        } 
    } // SearchResultCollection will be disposed here
}

Sie können dies dann wie folgt verwenden:

using(var srch = new DirectorySearcher(dirEnt, "(objectClass=Group)", loadProps))
{
    srch.PageSize = 1000;
    var results = SafeFindAll(srch);
}
Joe
quelle
4
Was ist, wenn im Vorfeld eine vorzeitige Kündigung erfolgt? Wird die Ergebnissammlung noch veröffentlicht?
Zerem
@kerem Vielleicht ist dies keine rechtzeitige Antwort auf Ihre Frage, aber die usingUrsachen Dispose(), die aufgerufen werden müssen, selbst wenn es eine Ausnahme gab (verwendet einen finallyBlock [ docs.microsoft.com/en-us/dotnet/csharp/language-reference/… tun Sie dies))
GuacoIV
@Joe Aus irgendeinem Grund stelle ich fest, dass "die Suche standardmäßig nicht ausgelagert ist (PageSize = 0). In diesem Fall werden bis zu SizeLimit-Ergebnisse zurückgegeben." scheint nicht wahr zu sein, wenn ein PrincipalSearcherzugrunde liegender Wert verwendet wird DirectorySearcher. Es zählt einfach weiter die Ergebnisse auf. Vielleicht die Serverseite oder PrincipalSearcherüberschreibt dies irgendwie ...
GuacoIV
1
@GuacoIV - Es ist sehr wahrscheinlich, dass PrincipalSearcherdas Standardverhalten überschrieben wird, insbesondere da die Eigenschaften PageSizeund nicht verfügbar gemacht SizeLimitwerden. Sie könnten dies wahrscheinlich bestätigen, indem Sie die DirectorySearcherzurückgegebene by- PrincipalSearcher.GetUnderlyingSearcherMethode untersuchen, um festzustellen, wie sie konfiguriert wurde.
Joe