I'd like to increase speed for finding users in a query similar to this:
using (PrincipalContext pc = PrincipalContext(ContextType.Domain))
using (UserPrincipal up = new UserPrincipal(pc) { SamAccountName = $"*{search}*" })
using (PrincipalSearcher ps = PrincipalSearcher(up))
{
...
}
Currently, the query searches the whole directory, taking a very long time.
I'd like to constrain the context to a specific container, but I only now a single portion of this container.
So, for instance, from a full LDAP path like this: OU=a,OU=b,OU=c,dc=d,dc=e,dc=loc I only have OU=b.
How can I retrieve the full LDAP path for using it in the context portion of the PrincipalContext constructor by using a class from System.DirectoryServices.AccountManagement having only a fraction of the path?
The root of your problem is this:
SamAccountName = $"*{search}*"Specifically, the
*at the beginning. ThesAMAccountNameattribute is indexed, so it is normally a very fast query. But since you have a wildcard at the beginning, it cannot use the index in this search. That means it has to look at every user in your domain to try and find a match.If you can change that to
$"{search}*", your problems will go away.But to answer your actual question,
If you really want to go through this, you will have to perform a search to find the OU and read the
distinguishedNamefor it. You can't do it withPrincipalSearchersince theSystem.DirectoryServices.AccountManagementnamespace just doesn't have any class for OUs. You will have to useDirectorySearcherdirectly (which is whatPrincipalSearcheruses in the background anyway). It would look something like this:Then you can use
ouDnas the base path for your user search.