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. The sAMAccountName
attribute 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,
I'd like to constrain the context to a specific container, but I only now a single portion of this container.
If you really want to go through this, you will have to perform a search to find the OU and read the distinguishedName
for it. You can't do it with PrincipalSearcher
since the System.DirectoryServices.AccountManagement
namespace just doesn't have any class for OUs. You will have to use DirectorySearcher
directly (which is what PrincipalSearcher
uses in the background anyway). It would look something like this:
var ouName = "b";
var search = new DirectorySearcher(new DirectoryEntry()) {
Filter = $"(&(objectClass=organizationalUnit)(name={ouName}))"
};
search.PropertiesToLoad.Add("distinguishedName");
var ou = search.FindOne();
var ouDn = ou.Properties["distinguishedName"][0];
Then you can use ouDn
as the base path for your user search.