我可以翻译成中文,问题标题为:“能否从DirectorySearcher获取1000条以上的记录?”

77
我刚注意到结果返回的列表被限制在1000条。我的域中有超过1000个组(庞大的域)。我如何获取超过1000条记录?我可以从后面的记录开始吗?我可以将其分成多个搜索吗?
这是我的查询:
DirectoryEntry dirEnt = new DirectoryEntry("LDAP://dhuba1kwtn004");
string[] loadProps = new string[] { "cn", "samaccountname", "name", "distinguishedname" };
DirectorySearcher srch = new DirectorySearcher(dirEnt, "(objectClass=Group)", loadProps);
var results = srch.FindAll();

我尝试设置srch.SizeLimit = 2000;,但好像没起作用。有什么想法吗?


重要的是要知道我们正在尝试循环遍历的内容。我们可能想要循环遍历LDAP记录列表(也称为DirectoryEntry)或者单个LDAP记录属性的值(list_类型)。当LDAP记录属性的值为_list_类型,即键值对列表时,需要循环遍历属性的值。例如_memberOf_属性的值是_list_类型。这个答案解释了:通过DirectoryEntry记录进行_paging vs 通过DirectoryEntry记录的属性列表值进行_Range检索_ - https://dev59.com/Jnrfs4cB2Jgan1znnean#12274460 - RBT
1个回答

188

如果想要获取所有结果,需要将DirectorySearcher.PageSize设置为非零值。

顺便提一下,当你使用完DirectorySearcher后,应该将其释放(dispose)。

using(var srch = new DirectorySearcher(dirEnt, "(objectClass=Group)", loadProps))
{
    srch.PageSize = 1000;
    var results = srch.FindAll();
}

API文档不是很清晰,但基本上:

  • 当您执行分页搜索时,SizeLimit被忽略,并且所有匹配的结果将随着您迭代FindAll返回的结果而返回。结果将一次从服务器检索一页。我选择了上面的1000值,但如果需要,可以使用较小的值。权衡是:使用较小的PageSize将更快地返回每个结果页面,但在迭代大量结果时将需要更频繁地调用服务器。

  • 默认情况下,搜索不是分页的(PageSize = 0)。在这种情况下,将返回最多SizeLimit个结果。

正如Biri指出的那样,重要的是处理FindAll返回的SearchResultCollection,否则可能会有内存泄漏如DirectorySearcher.FindAll的MSDN文档中的Remarks部分所述。

在.NET 2.0或更高版本中帮助避免这种情况的一种方法是编写一个自动处理SearchResultCollection的包装器方法。可能看起来像以下内容(或者可以成为.NET 3.5中的扩展方法):

public IEnumerable<SearchResult> SafeFindAll(DirectorySearcher searcher)
{
    using(SearchResultCollection results = searcher.FindAll())
    {
        foreach (SearchResult result in results)
        {
            yield return result;        
        } 
    } // SearchResultCollection will be disposed here
}

你可以按照以下方式使用它:

using(var srch = new DirectorySearcher(dirEnt, "(objectClass=Group)", loadProps))
{
    srch.PageSize = 1000;
    var results = SafeFindAll(srch);
}

4
如果在 foreach 循环中出现了提前终止,结果集合是否仍会被释放? - kerem
@kerem 或许这不是对你问题的及时回答,但 using 语句会在出现异常时调用 Dispose() 方法(使用 finallyhttps://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/using-statement#remarks)。 - GuacoIV
@Joe,出于某种原因,我发现“默认情况下搜索不分页(PageSize = 0)。在这种情况下,返回多达SizeLimit个结果。”当使用具有基础DirectorySearcher的PrincipalSearcher时,似乎并不正确。它继续枚举结果。也许是服务器端或PrincipalSearcher以某种方式覆盖了这一点... - GuacoIV
1
@GuacoIV - 很可能PrincipalSearcher正在覆盖默认行为,特别是因为它没有公开PageSizeSizeLimit属性。你可以通过检查PrincipalSearcher.GetUnderlyingSearcher方法返回的DirectorySearcher来确认这一点,以查看它的配置方式。 - Joe
你会在网上找到很多关于这个问题的帖子。有些非常令人困惑,似乎暗示无论你做什么都会有一个服务器端设置来破坏你的一天。从AD 2012开始,这是使用DirectorySearcher检索任意数量对象的正确答案。我已经尝试过检索18k个结果。srch.PageSize = int.MaxValue。效果很好。 - NadimAJ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接