我看到了使用 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.
这是我使用 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...
1000
PageSize
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);
}
使用 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 的区别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!