.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
相关产品推荐
相关产品推荐

