Reputation: 717
I am attempting to improve the performance of a searcher.FindAll() call to an active directory hierarchical group structure.
The code gets a SearchResultCollection of all of a user's groups, it then filters the groups on a search string. The SearchResultCollection collection has about 400 groups in it, and the filtered down version typically comes to 40. I am seeing no benefit from the built in cache during iterative calls (DirectorySearcher.CacheResults = True).
For example, if I call the code below 20 times in a row, the execution time is almost identical.
The below code receives the same penalty for all 400 iterations of the SearchResult every time it executes.
string groupFilter = "ExampleFilter";
DirectoryEntry root = GetRootDirectoryEntry();
string userPath = GetUserPath(username, root);
var searcher = new DirectorySearcher(root)
{
SearchScope = SearchScope.Subtree,
Filter = string.Format("(member:XXXX:={0})", userPath) + ""
//Any wildcard based search for distinguishedname like below returns no results, which is incorrect
//Filter = string.Format("(& (member:XXXX:={0}) (distinguishedname=*{1}) )", userPath, groupFilter)
};
searcher.PropertiesToLoad.Add("Name");
searcher.PropertiesToLoad.Add("distinguishedname");
var groupResults = searcher.FindAll();
var allFilteredGroups = new HashSet<string>();
foreach (SearchResult gr in groupResults) //approx 400 in the groupResults, same time penalty for every iteration, every time
{
var isRelevant = gr.Path.Contains(groupFilter);
if (isRelevant)
{
//Do Stuff
allFilteredGroups.Add(value);
}
}
return allFilteredGroups.ToList(); //approx 40
Why does the cache not offer any improvements? Any suggestions on how I could reduce the penalty for iterating all of these groups I know I do not want?
Upvotes: 0
Views: 733
Reputation: 41008
I assume you are trying to only include groups from a specific OU?
You are correct that you cannot filter by a partial distinguishedName
. You can, however, search only in one specific OU by modifying the SearchRoot
that you pass to DirectorySearcher
. For example:
DirectoryEntry root = new DirectoryEntry("LDAP://OU=MyGroups,DC=example,DC=com");
That DirectoryEntry
points to the MyGroups
OU. So if you pass that to DirectorySearcher
, then it will only search in that OU.
You can also set SearchScope
to OneLevel
if you don't want it to search the child OUs. Subtree
is the default, so if that's what you want, you don't need to set it at all.
Even if you want to find groups in multiple OUs, you may be better off repeating the search for each OU you want, rather than asking for everything and discarding most of the results.
Upvotes: 0