Получить пользовательский атрибут AD в одной партии - PullRequest
2 голосов
/ 22 августа 2011

Можно ли использовать библиотеку System.DirectoryServices.AccountManagement и класс PrincipalSearcher для извлечения пользовательского атрибута для всех принципалов, возвращенных из вызова на FindAll()?

В настоящее время я использую этот пример:http://msdn.microsoft.com/en-us/library/bb552835%28v=vs.90%29.aspx.

Однако при доступе к моему пользовательскому свойству / атрибуту кажется, что он совершает дополнительную поездку в хранилище AD.Я хотел бы, чтобы он с нетерпением загружал это свойство при первоначальном вызове FindAll().

Ответы [ 2 ]

4 голосов
/ 08 сентября 2011

Да, есть возможность загружать пользовательский атрибут для всех принципалов на начальном этапе. вызов FindAll (). Вам нужно только указать свои пользовательские атрибуты, как описано в примере Microsoft с использованием атрибута [DirectoryProperty ("YOUR_PROP_NAME")].

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

На моей машине коллекция насчитывает 68 объектов.

И тут начинается проблема и снижение производительности. Чем больше свойств включены в эту коллекцию, поэтому для их получения требуется больше обращений к Active Directory.

Я провел несколько тестов производительности:

Использование примера Microsoft для извлечения 200 объектов InetOrgPerson заняло около 500 мс.

Использование класса DirectorySearcher напрямую и только запрос интересующих свойств заняло всего 70 мс (см. образец ниже).

using (DirectoryEntry e = new DirectoryEntry("LDAP://server10/CN=users,DC=treyresearch,DC=net", 
                                         "treyresearch\\administrator", "P@$$W0rd", AuthenticationTypes.FastBind | AuthenticationTypes.Secure))
  {
    using (DirectorySearcher ds = new DirectorySearcher(e, "(&(objectCategory=inetorgperson)(logonCount=0))"))
    {
      ds.SearchScope = SearchScope.OneLevel;
      ds.PropertiesToLoad.Clear();
      ds.PropertiesToLoad.Add("logonCount");
      ds.PropertiesToLoad.Add("sAMAccountName");


      Stopwatch sw = new Stopwatch();
      sw.Start();
      int countPerson = 0;
      using (SearchResultCollection searchResultCol = ds.FindAll())
      {
        foreach (SearchResult sr in searchResultCol)
        {
          ResultPropertyValueCollection propCol = sr.Properties["logonCount"];

          if (propCol.Count > 0)
          {
            countPerson++;
            object cou = propCol[0];
          }
        }
        sw.Stop();
        Console.Out.WriteLine(sw.ElapsedMilliseconds);
        Console.Out.WriteLine(countPerson);
      }
    }
  }

По тому же признаку, что вместо этого я использовал objectCategory в фильтре поиска. из objectClass, потому что objectCategory является так называемым индексированным свойством. Доступ к индексированным свойствам быстрее, чем к неиндексированным свойствам.

Кроме того, я указал AuthenticationTypes.FastBind для улучшения производительность.

Для дальнейшего повышения производительности см. Эту статью на MSDN , описывающую, как создавать эффективные поисковые запросы.

В итоге, используя класс DirectorySearcher и указав только те свойства, которые вы заинтересован в творческом улучшении производительности вашего поиска (сокращении количества обращений к Active Directory).

Надеюсь, это поможет.

2 голосов
/ 07 сентября 2011

Да, вы можете; Примените GetUnderlyingObject () для каждого объекта Principal к DirectoryEntry, затем вы можете получить доступ к пользовательскому атрибуту, например oDE.Properties [YOUR_CUSTOM_ATTRIBUTE] .Value.

...