Active Directory を介して再帰的にユーザーの直属の部下をすべて取得しようとしています。したがって、ユーザーが与えられると、この人をマネージャーとして持つすべてのユーザー、またはマネージャーとしての人を持つマネージャーとしての人を持つすべてのユーザーのリストになります...最終的には入力ユーザーをマネージャーとして持ちます。
私の現在の試みはかなり遅いです:
private static Collection<string> GetDirectReportsInternal(string userDN, out long elapsedTime)
{
Collection<string> result = new Collection<string>();
Collection<string> reports = new Collection<string>();
Stopwatch sw = new Stopwatch();
sw.Start();
long allSubElapsed = 0;
string principalname = string.Empty;
using (DirectoryEntry directoryEntry = new DirectoryEntry(string.Format("LDAP://{0}",userDN)))
{
using (DirectorySearcher ds = new DirectorySearcher(directoryEntry))
{
ds.SearchScope = SearchScope.Subtree;
ds.PropertiesToLoad.Clear();
ds.PropertiesToLoad.Add("directReports");
ds.PropertiesToLoad.Add("userPrincipalName");
ds.PageSize = 10;
ds.ServerPageTimeLimit = TimeSpan.FromSeconds(2);
SearchResult sr = ds.FindOne();
if (sr != null)
{
principalname = (string)sr.Properties["userPrincipalName"][0];
foreach (string s in sr.Properties["directReports"])
{
reports.Add(s);
}
}
}
}
if (!string.IsNullOrEmpty(principalname))
{
result.Add(principalname);
}
foreach (string s in reports)
{
long subElapsed = 0;
Collection<string> subResult = GetDirectReportsInternal(s, out subElapsed);
allSubElapsed += subElapsed;
foreach (string s2 in subResult)
{
result.Add(s2);
}
}
sw.Stop();
elapsedTime = sw.ElapsedMilliseconds + allSubElapsed;
return result;
}
基本的に、この関数は入力として識別名 (CN=Michael Stum、OU=test、DC=sub、DC=domain、DC=com) を受け取ります。これにより、ds.FindOne() の呼び出しが遅くなります。
userPrincipalName を検索する方がはるかに高速であることがわかりました。私の問題: sr.Properties["directReports"] は単なる文字列のリストであり、それが識別名であり、検索が遅いようです。
私は、distinguishedName と userPrincipalName の間で変換する高速な方法はあるのだろうか? または、作業するのが識別名しかない場合、ユーザーを検索するより高速な方法はありますか?
編集:答えてくれてありがとう!Manager-Field を検索すると、機能が 90 秒から 4 秒に改善されました。これは新しく改善されたコードで、より高速で読みやすくなっています (経過時間機能にバグがある可能性が最も高いことに注意してください。ただし、関数の実際のコアは機能します)。
private static Collection<string> GetDirectReportsInternal(string ldapBase, string userDN, out long elapsedTime)
{
Collection<string> result = new Collection<string>();
Stopwatch sw = new Stopwatch();
sw.Start();
string principalname = string.Empty;
using (DirectoryEntry directoryEntry = new DirectoryEntry(ldapBase))
{
using (DirectorySearcher ds = new DirectorySearcher(directoryEntry))
{
ds.SearchScope = SearchScope.Subtree;
ds.PropertiesToLoad.Clear();
ds.PropertiesToLoad.Add("userPrincipalName");
ds.PropertiesToLoad.Add("distinguishedName");
ds.PageSize = 10;
ds.ServerPageTimeLimit = TimeSpan.FromSeconds(2);
ds.Filter = string.Format("(&(objectCategory=user)(manager={0}))",userDN);
using (SearchResultCollection src = ds.FindAll())
{
Collection<string> tmp = null;
long subElapsed = 0;
foreach (SearchResult sr in src)
{
result.Add((string)sr.Properties["userPrincipalName"][0]);
tmp = GetDirectReportsInternal(ldapBase, (string)sr.Properties["distinguishedName"][0], out subElapsed);
foreach (string s in tmp)
{
result.Add(s);
}
}
}
}
}
sw.Stop();
elapsedTime = sw.ElapsedMilliseconds;
return result;
}