You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET中如何为Active Directory搜索实现服务端分页?

.NET中Active Directory搜索的高效分页实现方案

要在域控制器端实现AD搜索的高效分页,同时获取符合条件的总记录数,可通过以下两种方案实现,避免客户端拉取全量数据后再处理:

方案一:使用DirectorySearcher + VirtualListView

该方案基于System.DirectoryServices,通过配置VirtualListView实现服务器端分页,并直接获取总记录数,适配大多数常规AD搜索场景。

代码示例

// 连接到目标AD域
using (var entry = new DirectoryEntry("LDAP://SAMPLE/DC=sample,DC=com"))
using (var searcher = new DirectorySearcher(entry))
{
    // 设置搜索过滤条件:SamAccountName包含test
    searcher.Filter = "(samAccountName=*test*)";
    // 指定需要返回的属性,减少不必要的数据传输
    searcher.PropertiesToLoad.Add("samAccountName");
    searcher.PropertiesToLoad.Add("displayName");

    // 配置分页参数
    int pageSize = 10;
    int currentPage = 0; // 从第0页开始计数
    int startIndex = currentPage * pageSize;

    // 启用VirtualListView实现服务器端分页
    searcher.VirtualListView = new DirectoryVirtualListView(
        startIndex,  // 当前页起始位置
        pageSize,    // 每页记录数
        0            // 初始总计数占位,搜索后会被服务器填充
    );

    // 执行搜索
    var results = searcher.FindAll();

    // 获取符合条件的总记录数
    int totalCount = searcher.VirtualListView.TotalCount;
    Console.WriteLine($"总记录数:{totalCount}");

    // 遍历当前页结果
    foreach (SearchResult result in results)
    {
        string samAccountName = result.Properties["samAccountName"][0].ToString();
        string displayName = result.Properties["displayName"][0].ToString();
        Console.WriteLine($"{samAccountName} - {displayName}");
    }
}

方案二:使用System.DirectoryServices.Protocols(底层LDAP协议)

该方案直接基于LDAP协议的分页控制扩展,灵活性更高,适合需要精细控制分页逻辑的复杂场景。

代码示例

// 配置LDAP连接参数
var ldapConfig = new LdapDirectoryIdentifier("SAMPLE");
using (var connection = new LdapConnection(ldapConfig))
{
    // 使用当前上下文身份验证,也可指定账号密码:connection.Credential = new NetworkCredential("user", "pwd");
    connection.AuthType = AuthType.Negotiate;
    connection.Bind();

    // 构建搜索请求
    string searchBase = "DC=sample,DC=com";
    string filter = "(samAccountName=*test*)";
    SearchScope scope = SearchScope.Subtree;
    string[] attributes = { "samAccountName", "displayName" };

    var searchRequest = new SearchRequest(
        searchBase,
        filter,
        scope,
        attributes
    );

    // 添加分页控制,设置每页大小
    int pageSize = 10;
    var pageControl = new PageResultRequestControl(pageSize);
    searchRequest.Controls.Add(pageControl);

    // 发送请求并获取响应
    var response = (SearchResponse)connection.SendRequest(searchRequest);

    // 提取分页响应控制,获取总记录数和分页标识
    PageResultResponseControl pageResponse = null;
    foreach (Control control in response.Controls)
    {
        if (control is PageResultResponseControl prc)
        {
            pageResponse = prc;
            break;
        }
    }

    if (pageResponse != null)
    {
        Console.WriteLine($"总记录数:{pageResponse.TotalCount}");
        // 若存在下一页,可通过pageResponse.Cookie获取分页标识,用于下一页请求
    }

    // 遍历当前页结果
    foreach (SearchResultEntry entry in response.Entries)
    {
        string samAccountName = entry.Attributes["samAccountName"][0].ToString();
        string displayName = entry.Attributes["displayName"][0].ToString();
        Console.WriteLine($"{samAccountName} - {displayName}");
    }
}

核心说明

  • 两种方案均在域控制器端完成分页逻辑,仅返回当前页的数据,避免客户端拉取全量结果,大幅提升大数据集下的性能。
  • 总记录数通过服务器返回的控制信息直接获取,无需客户端统计全量数据。
  • 注意:需确保目标AD域控制器支持对应的LDAP扩展(VirtualListView或PageResultControl),现代AD服务器均默认支持。

内容的提问来源于stack exchange,提问作者Akesh Jadhav

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 21:23:15