c# – 如何在拥有大量用户的Ldap服务器上进行分页搜索?
我需要创建一个使用.NET Core在
Linux上运行的LDAP客户端.我搜索了互联网,唯一支持.Net Standard的库是Novell.Directory.Ldap(开源,iei –
https://github.com/dsbenghe/Novell.Directory.Ldap.NETStandard).目录服务库在.Net Core for Linux中不支持,仅在Windows上.
我查看了文档并成功创建了一个基本的Ldap客户端应用程序. 现在问题是:我需要同步很多用户(10.000,200.000用户),默认情况下,我的ldap服务器的最大大小为1000页(我不想更改它).我使用VirtualListControl来创建页面,它适用于10k用户. 对于200k用户,它崩溃并出现错误53 – 不愿意对LdapSortControl响应执行. Novell库需要一个LdapSortControl才能执行分页操作(对于索引),我认为我的ldap无法对200k进行排序.我使用的代码: int startIndex = 1; int contentCount = 0; int afterIndex = 10; int count = 0; do { LdapVirtualListControl ctrl = new LdapVirtualListControl(startIndex,afterIndex,contentCount); LdapSortKey[] keys = new LdapSortKey[1]; keys[0] = new LdapSortKey("sn"); LdapSortControl sort = new LdapSortControl(keys,true); LdapSearchConstraints constraints = _ldapConnection.SearchConstraints; constraints.setControls(new LdapControl[] { ctrl,sort}); _ldapConnection.Constraints = constraints; LdapSearchResults lsc = _ldapConnection.Search(searchBase,searchScope,searchFilter,attributes,typesOnly,cons); while (lsc.HasMore()) { try { LdapEntry nextEntry = lsc.Next(); Console.WriteLine( nextEntry.DN); } catch (LdapException e) { Console.WriteLine($"Error: {e.LdapErrorMessage}"); //Exception is thrown,go for next entry continue; } } LdapControl[] controls = lsc.ResponseControls; if (controls == null) { Console.Out.WriteLine("No controls returned"); } else { foreach (LdapControl control in controls) { if (control.ID == "2.16.840.1.113730.3.4.10") { LdapVirtualListResponse response = new LdapVirtualListResponse(control.ID,control.Critical,control.getValue()); startIndex += afterIndex + 1; contentCount = response.ContentCount; count += afterIndex; } } } Console.WriteLine(i); } while (count <= contentCount); 文档很小,没有足够的信息,我不知道如何以更好的方式使用Novell库进行分页. 谢谢 解决方法
要使用Novell.Directory.Ldap进行分页查询,必须使用LdapVirtualListControl作为“请求”控件.
LdapVirtualListControl尊重Ldap排序请求控件的参数:VLV(虚拟列表视图),它们是: before:after:index:content_count 其中“之前”是您希望在索引之前返回的项目数,“之后”您希望在索引之后返回的项目数和“content_count”是服务器中预期的项目总数.如果你不知道它,你必须使用0作为值. 如果你想通过“ldapsearch”cli返回前5个元素,你必须使用:’0:4:1:0’和’0:4:5:0’用于后续的5个元素. LdapVirtualListControl拥有一个具有相同参数但具有不同顺序的构造函数: LdapVirtualListControl(int startIndex,int beforeCount,int afterCount,int contentCount) 就个人而言,我使用此函数正确设置参数: public static LdapSearchConstraints AddPagination(this LdapSearchConstraints constraints,int page,int pageSize) { int startIndex = (page - 1) * pageSize; startIndex++; int beforeCount = 0; int afterCount = pageSize - 1; int contentCount = 0; //0 means that i don't know the total count var lvlc = new LdapVirtualListControl(startIndex,beforeCount,afterCount,contentCount); constraints.setControls(lvlc); return constraints; } 之后,需要注意另一个问题:如果您要求在数据集结束后定位的一组数据,您将收到数据集的第一项. 说明: ldap中存在的数据示例: var lastIndex = (page * pageSize); if (lastIndex > result.Total) { var itemsToReturn = (int) (result.Total - (lastIndex - pageSize)); if (itemsToReturn < 1) { items = new List<LdapQueryItem>(); } else { items = items.Take(itemsToReturn).ToList(); } } 最后,获取总数的函数(在searchResults.HasMore()方法之后执行) protected int? GetTotal(LdapSearchResults searchResult) { if (searchResult == null) { throw new ArgumentNullException(nameof(searchResult)); } if (searchResult.ResponseControls != null && searchResult.ResponseControls.Any()) { foreach (LdapControl control in searchResult.ResponseControls) { if (control.ID == "2.16.840.1.113730.3.4.10") // the id of the response control { LdapVirtualListResponse response = new LdapVirtualListResponse(control.ID,control.getValue()); return response.ContentCount; } } } return null; } 您可以在本书中获得更多见解和信息: (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |