В .Net 4.0 может ли DirectorySearch возвращать результаты LDAP таким образом, чтобы я мог просматривать их? - PullRequest
7 голосов
/ 06 октября 2011

Я работаю в C # и пытаюсь использовать DirectorySearch для запроса групп очень большого LDAP-сервера Microsoft ActiveDirectory.

Итак, в моем приложении у меня будет постраничный списокгруппы, с возможностью поиска.Естественно, я не хочу забивать свой сервер LDAP, передавая мне полный набор результатов для этих запросов каждый раз, когда я нажимаю «Следующая страница».

Есть ли способ, используя DirectorySearch, получать ТОЛЬКО результаты одной произвольной страницы, а не возвращать весь набор результатов за один вызов метода?

Подобные вопросы:

Существует много подобных вопросов, когда кто-то спрашивает о подкачке страниц (имеется в виду от сервера LDAP к серверу приложений) и получает ответы, включающие PageSize и SizeLimit.Однако эти свойства влияют только на подкачку между сервером C # и сервером LDAP, и, в конце концов, единственные релевантные методы, которые есть в DirectorySearch, это FindOne () и FindAll ().

То, что я ищу, это в основном «FindPaged (pageSize, pageNumber)» (pageNumber - действительно важный бит. Я не просто хочу первые 1000 результатов, я хочу (например) 100Набор результатов 1000. Приложение не может дождаться, когда 100000 записей будут переданы с сервера LDAP на сервер приложений, даже если они разбиты на порции по 1000 записей.

Я понимаю, что DirectoryServices.Protocols имеет SearchRequest, который (я думаю?) Позволяет вам использовать «PageResultRequestControl», который выглядит так, как будто он имеет то, что я ищу (хотя похоже, что информация о подкачке приходит в «куки», что я неконечно, как я должен был бы восстановить). Но если есть способ сделать это без переписывания всей вещи для использования протоколов вместо этого, я бы предпочел не делать этого.

Я просто не могупредставьте себе, что нет никакого способа сделать это ... Даже в SQL есть Row_Number.

ОБНОВЛЕНИЕ: PageResultRequestControl не помогает - это только вперед и последовательно (Вы должны вызватьи получить первые N результатов, прежде чем вы сможете получить токен «cookie», необходимый для выполнения вызова, чтобы получить результат N + 1).

Однако cookie, по-видимому, имеет своего рода воспроизводимое упорядочение ...В наборе результатов, над которым я работал, я перебирал результаты один за другим, и каждый раз, когда печенье получалось таким образом:

1: {8, 0, 0, 0}
2: {11, 0, 0, 0}
3: {12, 0, 0, 0}
4: {16, 0, 0, 0}

Когда я перебирал два на два, я получал одинаковые числа (11, 16).Это заставляет меня думать, что если бы я мог выяснить код того, как генерируются эти числа, я мог бы создать специальный файл cookie, который дал бы мне именно тот поисковый вызов, который я ищу.

Ответы [ 3 ]

3 голосов
/ 12 октября 2011

К сожалению, похоже, что не может быть способа сделать это, учитывая текущие библиотеки C #.

Все стандартные библиотеки LDAP C # 4.0 возвращают результаты Top-N (например, FindAll (), который возвращает каждый результат, FindOne (), который возвращает первый результат, или SearchResult с PageResultRequestControl, который возвращает результаты N через N + M, но требует от вас получения результатов с 1 по N-1, прежде чем вы получите токен cookie, который вы можете передать с запросом для получения следующего набора.

Мне также не удалось найти сторонние библиотеки LDAP, которые бы позволяли это.

Пока не будет найдено лучшее решение, мой путь вперед будет состоять в том, чтобы изменить интерфейс, чтобы вместо этого отображать лучшие результаты X, без возможности подкачки клиента (очевидно, все еще использующий подкачку на стороне сервера в зависимости от ситуации).

Я могу использовать систему подкачки только для пересылки позже, передав обновленный файл cookie клиенту с ответом и передав его обратно одним нажатием кнопки типа «Дополнительные результаты». Возможно, на более позднем этапе стоит выяснить, могут ли эти файлы cookie быть созданы вручную.

UPDATE: Я поговорил со службой поддержки Microsoft и подтвердил это: динамический пейджинг с серверами LDAP невозможен. Это ограничение самих серверов LDAP.

Вы можете использовать Протоколы и элемент управления Пейджингом (если ваш сервер LDAP поддерживает это) для продвижения вперед по желанию, но не существует кросс-серверного (или даже кросс-версия) стандарта для куки, поэтому вы не можете разумно создайте свой собственный, и нет никакой гарантии, что куки могут быть использованы для повторных запросов.

Полное решение включает в себя использование протоколов (с пейджингом, как указано выше) для перетаскивания вашего выводимого на страницу результирующего набора в SQL, будь то во временную таблицу или таблицу постоянного хранения, и позволяет вашему пользователю просматривать страницу и разбирать результат THAT в традиционном манера. Имейте в виду, что ваши результаты не будут точно обновлены, но с некоторым интеллектуальным обновлением кэша вы сможете минимизировать этот риск.

3 голосов
/ 07 октября 2011

PageResultRequestControl - действительно способ сделать это, это часть протокола LDAP. Вам просто нужно выяснить, что это означает для вашего кода, извините. Должен быть способ использовать его там, где вы находитесь, но, сказав это, я работаю в Java, и мне просто нужно написать дюжину или около того элементов управления запросами и классов расширенных операций для использования с JNDI, чтобы вы могли может быть, не повезло ... или вам придется делать, как я. Внимание, разбор ASN.1 следует не так уж и далеко позади: - |

0 голосов
/ 11 января 2017

Может быть, вы хотите перебирать свои «страницы», используя атрибут range соответственно:

---- скопировать и вставить ----

В этом примере извлекаются записи 0-500 включительно.

DirectoryEntry group = new DirectoryEntry("LDAP://CN=Sales,DC=Fabrikam,DC=COM");
DirectorySearcher groupMember = new DirectorySearcher
    (group,"(objectClass=*)",new string[]{"member;Range=0-500"},SearchScope.Base);
SearchResult result = groupMember.FindOne();
// Each entry contains a property name and the path (ADsPath).
// The following code returns the property name from the PropertyCollection. 
String propName=String.Empty;
foreach(string s in result.Properties.PropertyNames)
{
    if ( s.ToLower() != "adspath")
    {
      propName = s;
      break;
    }
}
foreach(string member in result.Properties[propName])
{
     Console.WriteLine(member);
}

---- скопировать и вставить ----

для получения дополнительной информации см .:

Перечисление членов в большой группе https://msdn.microsoft.com/en-us/library/ms180907.aspx

Диапазон получения значений атрибутов https://msdn.microsoft.com/en-us/library/cc223242.aspx

Поиск с использованием поиска диапазона https://msdn.microsoft.com/en-us/library/aa367017.aspx

...