是的,可以在初次调用 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 的往返行程)。
希望这可以帮助。