Могу ли я получить более 1000 записей из DirectorySearcher в ASP.NET?
Я только что заметил, что список возвращаемых результатов ограничен 1000. У меня более 1000 групп в моем домене (огромный домен). Как я могу получить более 1000 записей? Могу ли я начать с более поздней записи? Можно ли разделить его на несколько поисков?
Вот мой запрос:
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();
Я попытался установить srch.SizeLimit = 2000;, но это не похоже на работу. Есть идеи?
2 ответа
Вам нужно установить DirectorySearcher.PageSize в ненулевое значение, чтобы получить все результаты.
Кстати, вы также должны избавиться от DirectorySearcher, когда вы закончите с ним
using(DirectorySearcher srch = new DirectorySearcher(dirEnt, "(objectClass=Group)", loadProps))
{
srch.PageSize = 1000;
var results = srch.FindAll();
}
Документация по API не очень понятна, но по существу:
когда вы выполняете постраничный поиск, SizeLimit игнорируется, и все совпадающие результаты возвращаются, когда вы перебираете результаты, возвращаемые FindAll. Результаты будут получены с сервера страницу за раз. Я выбрал значение 1000 выше, но вы можете использовать меньшее значение, если хотите. Компромисс: использование маленького PageSize вернет каждую страницу результатов быстрее, но потребует более частых обращений к серверу при переборе большого количества результатов.
по умолчанию поиск не разбит на страницы (PageSize = 0). В этом случае возвращается результат до SizeLimit.
Как отметил Бири, важно избавиться от коллекции SearchResultCollection, возвращаемой FindAll, в противном случае может возникнуть утечка памяти, как описано в разделе "Примечания" документации MSDN для DirectorySearcher.FindAll: http://msdn.microsoft.com/en-us/library/system.directoryservices.directorysearcher.findall.aspx
Одним из способов избежать этого в.NET 2.0 или более поздней версии является написание метода-оболочки, который автоматически удаляет SearchResultCollection. Это может выглядеть примерно так (или может быть методом расширения в.NET 3.5):
public IEnumerable<SearchResult> SafeFindAll(DirectorySearcher searcher)
{
using(SearchResultCollection results = searcher.FindAll())
{
foreach (SearchResult result in results)
{
yield return result;
}
} // SearchResultCollection will be disposed here
}
Затем вы можете использовать это следующим образом:
using(DirectorySearcher srch = new DirectorySearcher(dirEnt, "(objectClass=Group)", loadProps))
{
srch.PageSize = 1000;
var results = SafeFindAll(srch);
}
Я пытался использовать данное решение для разбивки на страницы, но оно не работает. Я установил pageSize = 100; и я получаю все элементы через searchResult.
dirSearcher = новый DirectorySearcher(direntry);dirSearcher.Filter = ("(| (objectClass = volume). (objectClass = user) (objectClass = printQueue) (objectClass = computer). (objectClass = organizationUnit) (objectClass = Group))");
dirSearcher.PageSize = 100;
dirSearcher.SearchScope = System.DirectoryServices.SearchScope.Subtree;
dirSearcher.ServerTimeLimit = new TimeSpan(1000);
//dirSearcher.VirtualListView = new DirectoryVirtualListView(0, 100, 1);
using (SearchResultCollection results = dirSearcher.FindAll())
{
foreach (SearchResult result in results)
{
DirectoryEntry ent = result.GetDirectoryEntry();
ADItem ProviderItem = Context.ConvertToItem(ent, true);
if (ProviderItem != null)
{
ProviderItem.IsPartialData = true;
ProviderItems.Add(ProviderItem);
}
}
}
}