本文介绍了PrincipalSearcher 和 DirectorySearcher 的区别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看到了使用 PrincipalSearcher 的 Active Directory 示例,以及使用 DirectorySearcher 执行相同操作的其他示例.这两个例子有什么区别?

I see Active Directory examples that use PrincipalSearcher and other examples that do the same thing but use DirectorySearcher. What is the difference between these two examples?

使用 PrincipalSearcher

PrincipalContext context = new PrincipalContext(ContextType.Domain);
PrincipalSearcher search = new PrincipalSearcher(new UserPrincipal(context));
foreach( UserPrincipal user in search.FindAll() )
{
    if( null != user )
        Console.WriteLine(user.DistinguishedName);
}

使用DirectorySearcher

DirectorySearcher search = new DirectorySearcher("(&(objectClass=user)(objectCategory=person))");
search.PageSize = 1000;
foreach( SearchResult result in search.FindAll() )
{
    DirectoryEntry user = result.GetDirectoryEntry();
    if( null != user )
        Console.WriteLine(user.Properties["distinguishedName"].Value.ToString());
}

推荐答案

我花了很多时间分析这两者之间的差异.这是我学到的.

I've spent a lot of time analyzing the differences between these two. Here's what I've learned.

  • DirectorySearcher 来自 System.DirectoryServices 命名空间.

PrincipalSearcher 来自 System.DirectoryServices.AccountManagement 命名空间,它建立在 System.DirectoryServices 之上.PrincipalSearcher 在内部使用 DirectorySearcher.

PrincipalSearcher comes from the System.DirectoryServices.AccountManagement namespace, which is built on top of System.DirectoryServices. PrincipalSearcher internally uses DirectorySearcher.

AccountManagement 命名空间(即 PrincipalSearcher)旨在简化用户、组和计算机对象(即主体)的管理.理论上,它的用法应该更容易理解,并且产生更少的代码行.尽管到目前为止,在我的实践中,这似乎在很大程度上取决于您在做什么.

The AccountManagement namespace (i.e. PrincipalSearcher) was designed to simplify management of User, Group, and Computer objects (i.e. Principals). In theory, it's usage should be easier to understand, and produce fewer lines of code. Though in my practice so far, it seems to heavily depend on what you're doing.

DirectorySearcher 更底层,可以处理的不仅仅是用户、组和计算机对象.

DirectorySearcher is more low-level and can deal with more than just User, Group and Computer objects.

对于一般用途,当您使用基本属性和只有几个对象时,PrincipalSearcher 将导致更少的代码行和更快的运行时间.

For general usage, when you're working with basic attributes and only a few objects, PrincipalSearcher will result in fewer lines of code and faster run time.

随着您正在执行的任务变得越高级,优势似乎就会消失.例如,如果您期望获得超过几百个结果,则必须获取基础 DirectorySearcher 并设置 PageSize

The advantage seems to disappear the more advanced the tasks you're doing become. For instance if you're expecting more than few hundred results, you'll have to get the underlying DirectorySearcher and set the PageSize

DirectorySearcher ds = search.GetUnderlyingSearcher() as DirectorySearcher;
if( ds != null )
    ds.PageSize = 1000;

如果您使用 PropertiesToLoad

  • DirectorySearcher 可以比 PrincipalSearcher 快得多.

  • DirectorySearcher can be significantly faster than PrincipalSearcher if you make use of PropertiesToLoad.

    DirectorySearcher 和类似的类可以处理 AD 中的所有对象,而 PrincipalSearcher 的限制要大得多.例如,您不能使用 PrincipalSearcher 和类似的类来修改组织单位.

    DirectorySearcher and like classes can work with all objects in AD, whereas PrincipalSearcher is much more limited. For example, you can not modify an Organizational Unit using PrincipalSearcher and like classes.

    这是我使用 PrincipalSearcherDirectorySearcher 而不使用 PropertiesToLoadDirectorySearcher 来分析的图表使用 PropertiesToLoad.所有测试...

    Here is a chart I made to analyze using PrincipalSearcher, DirectorySearcher without using PropertiesToLoad, and DirectorySearcher with using PropertiesToLoad. All tests...

    • 使用 1000
    • PageSize
    • 一共查询了4278个用户对象
    • 指定以下条件
      • objectClass=user
      • objectCategory=person
      • 不是调度资源(即 !msExchResourceMetaData=ResourceType:Room)
      • 已启用(即 !userAccountControl:1.2.840.113556.1.4.803:=2)


      使用PrincipalSearcher

      [DirectoryRdnPrefix("CN")]
      [DirectoryObjectClass("Person")]
      public class UserPrincipalEx: UserPrincipal
      {
      
          private AdvancedFiltersEx _advancedFilters;
      
          public UserPrincipalEx( PrincipalContext context ): base(context)
          {
              this.ExtensionSet("objectCategory","User");
          }
      
          public new AdvancedFiltersEx AdvancedSearchFilter
          {
              get {
                  if( null == _advancedFilters )
                      _advancedFilters = new AdvancedFiltersEx(this);
                      return _advancedFilters;
              }
          }
      
      }
      
      public class AdvancedFiltersEx: AdvancedFilters 
      {
      
          public AdvancedFiltersEx( Principal principal ): 
              base(principal) { }
      
          public void Person()
          {
              this.AdvancedFilterSet("objectCategory", "person", typeof(string), MatchType.Equals);
              this.AdvancedFilterSet("msExchResourceMetaData", "ResourceType:Room", typeof(string), MatchType.NotEquals);
          }
      }
      
      //...
      
      for( int i = 0; i < 10; i++ )
      {
          uint count = 0;
          Stopwatch timer = Stopwatch.StartNew();
          PrincipalContext context = new PrincipalContext(ContextType.Domain);
          UserPrincipalEx filter = new UserPrincipalEx(context);
          filter.Enabled = true;
          filter.AdvancedSearchFilter.Person();
          PrincipalSearcher search = new PrincipalSearcher(filter);
          DirectorySearcher ds = search.GetUnderlyingSearcher() as DirectorySearcher;
          if( ds != null )
              ds.PageSize = 1000;
          foreach( UserPrincipalEx result in search.FindAll() )
          {
              string canonicalName = result.CanonicalName;
              count++;
          }
      
          timer.Stop();
          Console.WriteLine("{0}, {1} ms", count, timer.ElapsedMilliseconds);
      }
      


      使用DirectorySearcher

      for( int i = 0; i < 10; i++ )
      {
          uint count = 0;
          string queryString = "(&(objectClass=user)(objectCategory=person)(!msExchResourceMetaData=ResourceType:Room)(!userAccountControl:1.2.840.113556.1.4.803:=2))";
      
          Stopwatch timer = Stopwatch.StartNew();
      
          DirectoryEntry entry = new DirectoryEntry();
          DirectorySearcher search = new DirectorySearcher(entry,queryString);
          search.PageSize = 1000;
          foreach( SearchResult result in search.FindAll() )
          {
              DirectoryEntry user = result.GetDirectoryEntry();
              if( user != null )
              {
                  user.RefreshCache(new string[]{"canonicalName"});
                  string canonicalName = user.Properties["canonicalName"].Value.ToString();
                  count++;
              }
          }
          timer.Stop();
          Console.WriteLine("{0}, {1} ms", count, timer.ElapsedMilliseconds);
      }
      


      使用 DirectorySearcherPropertiesToLoad

      Using DirectorySearcher with PropertiesToLoad

      与使用DirectorySearcher"相同,但添加这一行

      Same as "Using DirectorySearcher but add this line

      search.PropertiesToLoad.AddRange(new string[] { "canonicalName" });
      

      之后

      search.PageSize = 1000;
      

      这篇关于PrincipalSearcher 和 DirectorySearcher 的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

  • 10-20 12:24