Разница между PrincipalSearcher и DirectorySearcher
Я вижу примеры Active Directory, которые используют PrincipalSearcher
и другие примеры, которые делают то же самое, но использовать 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());
}
2 ответов
я потратил много времени на анализ различий между этими двумя. Вот что я узнал.
DirectorySearcher
происходит отSystem.DirectoryServices
пространство имен.PrincipalSearcher
происходит отSystem.DirectoryServices.AccountManagement
пространство имен, которое построено поверхSystem.DirectoryServices
.PrincipalSearcher
внутренне используетDirectorySearcher
.на
AccountManagement
пространство имен (т. е.PrincipalSearcher
) был разработан для упрощения управления пользовательскими, групповыми и компьютерными объектами (т. е. Принципалы.) Теоретически, это использование должно быть проще понять и производить меньше строк кода. Хотя в моей практике это сильно зависит от того, что вы делаете.DirectorySearcher
более низкоуровнево и может общаться с больше чем как раз объектами потребителя, группы и компьютера.для общего использования, когда вы работаете с основными атрибутами и лишь немногие объекты,
PrincipalSearcher
приведет к меньшему количеству строк кода и более быстрому времени выполнения.-
преимущество, кажется, исчезает тем более продвинутые задачи, которые вы делаете становятся. Например, если вы ожидаете более нескольких сотен результатов, вам нужно будет получить базовый
DirectorySearcher
и выберитеPageSize
DirectorySearcher ds = search.GetUnderlyingSearcher() as DirectorySearcher; if( ds != null ) ds.PageSize = 1000;
DirectorySearcher
может быть значительно быстрее, чемPrincipalSearcher
если вы используетеPropertiesToLoad
.DirectorySearcher
и подобные классы могут работать со всеми объектами в AD, тогда какPrincipalSearcher
намного более ограниченный. Например, нельзя изменить организационное подразделение с помощьюPrincipalSearcher
и как классы.
вот график для анализа с помощью PrincipalSearcher
, DirectorySearcher
без использования PropertiesToLoad
и DirectorySearcher
С помощью PropertiesToLoad
. Все тесты...
- использовать
PageSize
of1000
- запрос в общей сложности 4,278 пользовательских объектов
- указать следующие критерий
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
но добавьте эту строку
search.PropertiesToLoad.AddRange(new string[] { "canonicalName" });
после
search.PageSize = 1000;
PrincipalSearcher
используется для запроса каталога для групп или пользователей. DirectorySearcher
используется для запроса всех видов объектов.
Я DirectorySearcher
чтобы получить группы до того, как я обнаружил PrincipalSearcher
поэтому, когда я заменил первый на последний, скорость моей программы улучшилась (может быть, это было просто PrincipalSearcher
Это создало лучший запрос для меня. За то, что я забочусь, PrincipalSearcher
было просто проще в использовании и больше подходит для задачи получения участников.
DirectorySearcher
С другой стороны, это больше общие, как это может получить другие виды объектов. Вот почему он не может быть строго набран, как указано в комментариях. PrincipalSearcher
все о субъектах, поэтому у него будут строго типизированные объекты, относящиеся к субъектам, и поэтому вам также не нужно говорить об этом, чтобы получить объект пользователя или группы, это будет подразумеваться основными классами, которые вы используете.