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

使用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());
}

===============>>#1 票数:71 已采纳

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

  • DirectorySearcher来自System.DirectoryServices名称空间。

  • PrincipalSearcher来自System.DirectoryServices.AccountManagement命名空间,该命名空间构建在System.DirectoryServices之上。 PrincipalSearcher内部使用DirectorySearcher

  • AccountManagement命名空间(即PrincipalSearcher )旨在简化用户,组和计算机对象(即主体)的管理。 理论上,它的使用应该更容易理解,并产生更少的代码行。 虽然在我的实践中到目前为止,它似乎在很大程度上依赖于你正在做的事情。

  • DirectorySearcher更低级,可以处理的不仅仅是User,Group和Computer对象。

  • 对于一般用法,当您使用基本属性和少量对象时, PrincipalSearcher将减少代码行数并缩短运行时间。

  • 优势似乎消失了,你所做的任务越先进。 例如,如果您期望超过几百个结果,则必须获取基础DirectorySearcher并设置PageSize

     DirectorySearcher ds = search.GetUnderlyingSearcher() as DirectorySearcher; if( ds != null ) ds.PageSize = 1000; 
  • 如果您使用PropertiesToLoad DirectorySearcher可以比PrincipalSearcher快得多。

  • DirectorySearcher和类似的类可以处理AD中的所有对象,而PrincipalSearcher则更加有限。 例如,您无法使用PrincipalSearcher和类似的类修改组织单位。

这里有一个图表我用做分析PrincipalSearcherDirectorySearcher不使用PropertiesToLoadDirectorySearcher使用PropertiesToLoad 所有测试......

  • 使用PageSize1000
  • 查询总共4,278个用户对象
  • 指定以下条件
    • objectClass=user
    • objectCategory=person
    • 不是调度资源(即!msExchResourceMetaData=ResourceType:Room
    • 启用(即!userAccountControl:1.2.840.113556.1.4.803:=2

DirectorySearcher与PrincipalSearcher性能图表


每个测试的代码


使用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

与“使用DirectorySearcher但添加此行相同”

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

search.PageSize = 1000;

===============>>#2 票数:3

PrincipalSearcher用于查询组或用户的目录。 DirectorySearcher用于查询各种对象。

我使用DirectorySearcher获取组之前我发现了PrincipalSearcher所以当我用后者替换前者时,我的程序速度得到了提高(也许只是PrincipalSearcher为我创建了一个更好的查询。对于我关心的, PrincipalSearcher更容易使用和更适合获得目的的任务。

另一方面, DirectorySearcher更通用,因为它可以获得其他类型的对象。 这就是为什么它不能像评论中提到的那样强类型化。 PrincipalSearcher是关于主体的所有内容,因此它将具有与主体相关的强类型对象,这就是为什么你也不需要告诉它为你提供类型用户或组的对象,它将由Principal类隐含采用。

  ask by Drew Chapin translate from so

未解决问题?本站智能推荐: