はい、FindAll() の最初の呼び出しで、すべてのプリンシパルのカスタム属性を積極的に読み込むことができます。[DirectoryProperty("YOUR_PROP_NAME")] 属性を使用して、Microsoft のサンプルで説明されているように、カスタム属性を指定するだけで済みます。
UserPrincipal クラスの GetUnderlyingSearcher() メソッドを使用して、基になる DirectorySearcher のプロパティ PropertiesToLoad にアクセスすると、ロードするプロパティのコレクションにカスタム属性が含まれていることがわかります。デバッガーで PropertiesToLoad コレクションを調べることができます。
私のマシンでは、コレクションには合計 68 個のプロパティが含まれています。
そして、ここから問題とパフォーマンスの低下が始まります。このコレクションに含まれるプロパティが多いほど、それらを取得するために必要な Active Directory へのラウンド トリップが多くなります。
私はいくつかのパフォーマンステストを行いました:
Microsoft のサンプルを使用して 200 個の InetOrgPerson オブジェクトを取得するのに約 500 ミリ秒かかりました。
DirectorySearcher クラスを直接使用して、関心のあるプロパティのみを要求すると、わずか 70 ミリ秒かかりました (以下のサンプルを参照)。
using (DirectoryEntry e = new DirectoryEntry("LDAP://server10/CN=users,DC=treyresearch,DC=net",
"treyresearch\\administrator", "P@$$W0rd", AuthenticationTypes.FastBind | AuthenticationTypes.Secure))
{
using (DirectorySearcher ds = new DirectorySearcher(e, "(&(objectCategory=inetorgperson)(logonCount=0))"))
{
ds.SearchScope = SearchScope.OneLevel;
ds.PropertiesToLoad.Clear();
ds.PropertiesToLoad.Add("logonCount");
ds.PropertiesToLoad.Add("sAMAccountName");
Stopwatch sw = new Stopwatch();
sw.Start();
int countPerson = 0;
using (SearchResultCollection searchResultCol = ds.FindAll())
{
foreach (SearchResult sr in searchResultCol)
{
ResultPropertyValueCollection propCol = sr.Properties["logonCount"];
if (propCol.Count > 0)
{
countPerson++;
object cou = propCol[0];
}
}
sw.Stop();
Console.Out.WriteLine(sw.ElapsedMilliseconds);
Console.Out.WriteLine(countPerson);
}
}
}
同様に、objectCategory はいわゆるインデックス付きプロパティであるため、objectClass の代わりに検索フィルターで objectCategory を使用しました。インデックス付きプロパティへのアクセスは、インデックス付きでないプロパティへのアクセスよりも高速です。
さらに、パフォーマンスを向上させるために AuthenticationTypes.FastBind を指定しました。
パフォーマンスをさらに向上させるには、効率的な検索クエリを作成する方法について説明しているMSDNの記事を参照してください。
要約すると、DirectorySearcher クラスを使用し、関心のあるプロパティのみを指定すると、検索のパフォーマンスが大幅に向上します (Active Directory へのラウンド トリップが減少します)。
お役に立てれば。