问题描述
我看到使用 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
of1000
- 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
withPropertiesToLoad
与使用
DirectorySearcher
相同,但添加以下行Same as "Using
DirectorySearcher
but add this linesearch.PropertiesToLoad.AddRange(new string[] { "canonicalName" });
之后
search.PageSize = 1000;
这篇关于PrincipalSearcher和DirectorySearcher之间的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!
-