Улучшение кэширования System.DirectoryServices.DirectorySearcher или фильтрация FindAll () - PullRequest
0 голосов
/ 15 февраля 2020

Я пытаюсь улучшить производительность поиска. Вызов функции FindAll () для иерархической структуры группы активного каталога.

Код получает SearchResultCollection всех групп пользователей, а затем фильтрует группы в строке поиска. Коллекция SearchResultCollection содержит около 400 групп, а отфильтрованная версия обычно достигает 40. Я не вижу никакой пользы от встроенного кэша во время итеративных вызовов (DirectorySearcher.CacheResults = True).

Например, если я вызываю код ниже 20 раз подряд, время выполнения почти идентично.

  1. Я видел эту ссылку DirectorySearcher Filter и понимаю, что DistinguishedName недоступно для подстановочного поиска в свойстве Searcher.Filter (я подтвердил с помощью тестов, я бы предпочел DirectorySearcher для обработки фильтрации)
  2. По умолчанию для объекта DirectorySearcher включено кэширование, но, похоже, здесь это совсем не помогает (в любом случае я установил для него значение True)
  3. В документации указано, что DirectorySearcher будет решите НЕ кэшировать, если есть большой результат, есть идеи, что это за порог?

Приведенный ниже код получает одно и то же наказание за все 400 итераций SearchResult при каждом выполнении.

 string groupFilter = "ExampleFilter";
 DirectoryEntry root = GetRootDirectoryEntry();
 string userPath = GetUserPath(username, root);
 var searcher = new DirectorySearcher(root)
 {
    SearchScope = SearchScope.Subtree,
    Filter =  string.Format("(member:XXXX:={0})", userPath) + ""
    //Any wildcard based search for distinguishedname like below returns no results, which is incorrect        
    //Filter =  string.Format("(& (member:XXXX:={0}) (distinguishedname=*{1}) )", userPath, groupFilter)  
 };

 searcher.PropertiesToLoad.Add("Name");
 searcher.PropertiesToLoad.Add("distinguishedname");   
 var groupResults = searcher.FindAll();

 var allFilteredGroups = new HashSet<string>();

 foreach (SearchResult gr in groupResults) //approx 400 in the groupResults, same time penalty for every iteration, every time
 {
      var isRelevant = gr.Path.Contains(groupFilter);
      if (isRelevant)
      {
          //Do Stuff
          allFilteredGroups.Add(value); 
      }
  }

  return allFilteredGroups.ToList(); //approx 40

Почему в кеше нет улучшений? Любые предложения о том, как я мог бы уменьшить штраф за итерацию всех этих групп, я знаю, что я не хочу?

1 Ответ

0 голосов
/ 03 марта 2020

Я предполагаю, что вы пытаетесь включить группы только из указанного c OU?

Вы правы, что вы не можете фильтровать по частичной distinguishedName. Однако вы можете искать только в одном указанном c OU, изменив SearchRoot, который вы передаете DirectorySearcher. Например:

DirectoryEntry root = new DirectoryEntry("LDAP://OU=MyGroups,DC=example,DC=com");

Это DirectoryEntry указывает на MyGroups OU. Поэтому, если вы передадите это в DirectorySearcher, он будет искать только в этом OU.

Вы также можете установить SearchScope в OneLevel, если не хотите, чтобы он осуществлял поиск дочерних OU. Subtree - это значение по умолчанию, поэтому, если это то, что вам нужно, вам вообще не нужно его устанавливать.

Даже если вы хотите найти группы в нескольких подразделениях, вам лучше повторить поиск для каждой нужной OU вместо того, чтобы просить все и отбрасывать большинство результатов.

...