Разница между 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и выберитеPageSizeDirectorySearcher ds = search.GetUnderlyingSearcher() as DirectorySearcher; if( ds != null ) ds.PageSize = 1000; DirectorySearcherможет быть значительно быстрее, чемPrincipalSearcherесли вы используетеPropertiesToLoad.DirectorySearcherи подобные классы могут работать со всеми объектами в AD, тогда какPrincipalSearcherнамного более ограниченный. Например, нельзя изменить организационное подразделение с помощьюPrincipalSearcherи как классы.
вот график для анализа с помощью PrincipalSearcher, DirectorySearcher без использования PropertiesToLoad и DirectorySearcher С помощью PropertiesToLoad. Все тесты...
- использовать
PageSizeof1000 - запрос в общей сложности 4,278 пользовательских объектов
- указать следующие критерий
objectClass=userobjectCategory=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 все о субъектах, поэтому у него будут строго типизированные объекты, относящиеся к субъектам, и поэтому вам также не нужно говорить об этом, чтобы получить объект пользователя или группы, это будет подразумеваться основными классами, которые вы используете.