本文介绍了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 来自系统。 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;


  • DirectorySearcher 可以明显更快比使用 PropertiesToLoad 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.

    这是我使用 PrincipalSearcher 进行分析的图表, DirectorySearcher 而不使用 PropertiesToLoad DirectorySearcher 并使用 PropertiesToLoad 。所有测试...

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


    • 使用 PageSize 中的 1000

    • 查询总共4,278个用户对象

    • 指定以下条件


      • objectClass = user

      • objectCategory = person

      • 不是调度资源(即!msExchResourceMetaData = ResourceType:Room

      • 已启用(即!userAccountControl:1.2.840.113556.1.4.803:= 2

      • Use a PageSize of 1000
      • Query a total of 4,278 user objects
      • Specify the following criteria
        • objectClass=user
        • objectCategory=person
        • Not a scheduling resource (i.e. !msExchResourceMetaData=ResourceType:Room)
        • Enabled (i.e. !userAccountControl:1.2.840.113556.1.4.803:=2)


        使用 PrincipalSearcher

        Using 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

        Using 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);
        }
        


        DirectorySearcher PropertiesToLoad 一起使用

        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