Active Directory搜索的有效分页

Dar*_*rov 20 .net c# active-directory

什么是在.NET中进行Active Directory搜索分页的有效方法?在AD中搜索的方法有很多,但到目前为止我找不到如何有效地进行搜索.我希望能够指示SkipTake参数,并能够检索与结果中的搜索条件匹配的记录总数.

我试过在PrincipalSearcher课堂上搜索:

using (var ctx = new PrincipalContext(ContextType.Domain, "FABRIKAM", "DC=fabrikam,DC=com"))
using (var criteria = new UserPrincipal(ctx))
{
    criteria.SamAccountName = "*foo*";

    using (var searcher = new PrincipalSearcher(criteria))
    {
        ((DirectorySearcher)searcher.GetUnderlyingSearcher()).SizeLimit = 3;
        var results = searcher.FindAll();
        foreach (var found in results)
        {
            Console.WriteLine(found.Name);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在这里,我能够将搜索结果限制为3但是我无法获得与我的搜索条件(SamAccountName包含foo)相对应的记录总数.我也没有能够向搜索者指示跳过前50个记录.

我也试过使用System.DirectoryServices.DirectoryEntry,System.DirectoryServices.Protocols.SearchRequest但我唯一能做的就是指定页面大小.

那么获取客户端上的所有结果并在那里进行跳过和计数的唯一方法是什么?我真的希望有更有效的方法直接在域控制器上实现这一点.

小智 9

如果 SizeLimit 设置为零且 PageSize 设置为 500,则搜索将在包含 500 个项目的页面中返回所有 12,000 个结果,最后一页仅包含 200 个项目。分页对应用程序来说是透明的,除了将 PageSize 属性设置为正确的值之外,应用程序无需执行任何特殊处理。

SizeLimit 限制您一次可以检索的结果数量 - 因此您的 PageSize 需要小于或等于 1000(Active Directory 将搜索结果的最大数量限制为 1000。在这种情况下,将 SizeLimit 属性设置为更大的值超过 1000 没有影响。)。当您调用 FindAll() 等时,分页会在幕后自动完成。

更多详情请参考MSDN

https://msdn.microsoft.com/en-us/library/ms180880.aspx

https://msdn.microsoft.com/en-us/library/system.directoryservices.directorysearcher.pagesize.aspx

https://msdn.microsoft.com/en-us/library/system.directoryservices.directorysearcher.sizelimit.aspx


bal*_*ate 8

您可以尝试虚拟列表视图搜索.下面按cn对用户进行排序,然后从第100个用户开始获取51个用户.

    DirectoryEntry rootEntry = new DirectoryEntry("LDAP://domain.com/dc=domain,dc=com", "user", "pwd");

    DirectorySearcher searcher = new DirectorySearcher(rootEntry);
    searcher.SearchScope = SearchScope.Subtree;
    searcher.Filter = "(&(objectCategory=person)(objectClass=user))";
    searcher.Sort = new SortOption("cn", SortDirection.Ascending);
    searcher.VirtualListView = new DirectoryVirtualListView(0, 50, 100);

    foreach (SearchResult result in searcher.FindAll())
    {
        Console.WriteLine(result.Path);
    }
Run Code Online (Sandbox Code Playgroud)

对于您的用例,您只需要DirectoryVirtualListView的BeforeCount,AfterCount和Offset属性(DirectoryVirtualListView ctor中的3).DirectoryVirtualListView的文档非常有限.您可能需要对其行为进行一些实验.


Sad*_*ida -1

    private static DirectoryEntry forestlocal = new DirectoryEntry(LocalGCUri, LocalGCUsername, LocalGCPassword);
    private DirectorySearcher localSearcher = new DirectorySearcher(forestlocal);

     public List<string> GetAllUsers() 
    {
        List<string> users = new List<string>();

        localSearcher.SizeLimit = 10000;
        localSearcher.PageSize = 250;

        string localFilter = string.Format(@"(&(objectClass=user)(objectCategory=person)(!(objectClass=contact))(msRTCSIP-PrimaryUserAddress=*))");

        localSearcher.Filter = localFilter;

        SearchResultCollection localForestResult;

        try
        {
            localForestResult = localSearcher.FindAll();

            if (resourceForestResult != null) 
            {

                foreach (SearchResult result in localForestResult) 
                {
                    if (result.Properties.Contains("mail"))
                        users.Add((string)result.Properties["mail"][0]);
                }

            }

        }
        catch (Exception ex) 
        {

        }

        return users;
    }
Run Code Online (Sandbox Code Playgroud)

  • 我不太明白这个 PageSize 和 SizeLimit 是如何工作的。假设我指定“SizeLimit=1000”和“PageSize=5”,并且有 200 个用户符合我的搜索条件。现在我想要获得 195-200 个用户。此示例是否会通过向 AD 发出 40 个请求来将所有 200 个用户返回给客户端?然后我必须在客户端上对这 200 个用户进行分页才能从 195 到 200 中提取用户?如果这是真的,这是唯一的方法吗?我的意思是,如果我要丢弃用户 1-195,那么将用户 1-195 交给客户端对我来说似乎完全是一种浪费,因为在我的 UI 中我想显示 195-200。 (2认同)