Я пишу метод на C#, который должен запрашивать Active Directory и находить всех пользователей и группы с отображаемым именем формата {displayName} (поиск подстановочных знаков с использованием как стартового, так и конечного шаблона), этот метод будет использоваться для поля автозаполнения.Активный запрос каталога с подстановочными знаками имеет низкую производительность
Проблема в производительности метода, который я написал, очень низок, попытка запроса AD занимает от 30 секунд до полной минуты в зависимости от строки запроса.
AD моей организации очень большой, но если это займет много времени, поле автозаполнения будет бессмысленным.
Вот код, я использую прямо сейчас:
// Intialize the results list.
result.queryResult = new List<Classses.ADSearchObject>();
// Set up domain context.
PrincipalContext pc = new PrincipalContext(ContextType.Domain, Domain, Constants.adQueryUser, Constants.adQueryPassword);
// Set up a directory searcher.
DirectorySearcher dSearcher = new DirectorySearcher();
// Define a SearchCollection to store the results.
SearchResultsCollection searchCol;
// Define returned result paging for performance.
dSearcher.PageSize = 1000;
// Define the properties to retrieve
dSearcher.PropertiesToLoad.Add("sAMAccountName");
dSearcher.PropertiesToLoad.Add("displayName");
// Define the filter for users.
dSearcher.Filter = $"(|(&(displayName = {result.querystring}*)(objectCategory=person))(&(displayName=*{result.querystring})(objectCategory=person)))";
// Search based in filter and save the results.
searchCol = dSearcher.FindAll();
// Add the results to the returned object
foreach (SearchResult searchResult in searchCol)
{
DirectoryEntry de = searchResult.GetDirectoryEntry();
// Code to get data from the results...
}
// Define the filter for groups.
dSearcher.Filter = $"(|(&(displayName={result.querystring}*)(objectCategory=person))(&(displayName=*{result.querystring})(objectCategory=person)))";
// Search based in filter and save the results.
searchCol = dSearcher.FindAll();
// Add the results to the returned object
foreach (SearchResult searchResult in searchCol)
{
DirectoryEntry de = searchResult.GetDirectoryEntry();
// Code to get data from the results...
}
В настоящее время поиск разделяется для пользователей и групп, чтобы сделать его легко отличить их, но если это повышает производительность существенно я унифицировать их к один поиск.
Edit: Как предложила Rene пользователя, я использовал Stopwatch
, чтобы проверить время, необходимое для FindAll
и я также проверил, как долго мои foreach
петель взять.
Я узнал, что вызовы FindAll
занимают около 100 мс (очень быстро) даже при поиске с помощью главного шаблона (который нет), индексированного AD.
По-видимому, звонки, которые занимают больше всего времени, - это мои петли foreach
, которые занимают около 40 секунд (40 000 мс).
Я обновляю вопрос с блоком кода в моих foreach
петлях, как я не понял, как улучшить свою работу:
// --- I started a stopwatch here
foreach (SearchResult searchResult in searchCol)
{
// --- I stopped the stopwatch here and noticed it takes about 30,000ms
result.code = 0;
DirectoryEntry de = searchResult.GetDirectoryEntry();
ADSearchObject adObj = new ADSearchObject();
adObj.code = 0;
if (de.Properties.Contains("displayName")
{
adObj.displayName = de.Properties["displayName"].Value.ToString();
}
adObj.type = "user";
result.queryResults.Add(adObj);
}
Примечания, где я начал и остановился мой «Секундомер» в моем обновленном код, я не знаю, почему начало цикла занимает так много времени.
Так оно работает, когда вы имеете дело с Microsoft AD.Возможно, вы можете придумать синхронизацию дерева AD с каким-то БД, который позволит вам выполнять запросы в миллисекундах, а не запрашивать AD каждый раз. – r1verside
Не будет '(& (displayName = * {result.querystring} *) (objectCategory = person))' делать то же, что и ваш фильтр? И вы можете StopWatch называть «FindAll». Они занимают больше всего времени? – rene
@rene, пожалуйста, посмотрите на редактирование, которое я сделал для сообщения, я добавил несколько раз из «Секундомера», который я открыл в разных частях кода. –