在 .Net 4.0 中,DirectorySearch 能否以允许我分页的方式返回 LDAP 结果?

发布于 2024-12-08 07:43:51 字数 1499 浏览 0 评论 0原文

我正在使用 C# 工作,并尝试使用 DirectorySearch 来查询非常大的 Microsoft ActiveDirectory LDAP 服务器的组。

因此,在我的应用程序中,我将拥有一个具有搜索功能的分页组列表。当然,我不想每次点击“下一页”时都将这些查询的整个结果集传递给我的 LDAP 服务器。

有没有一种方法,使用 DirectorySearch 仅检索单个任意页面的结果,而不是在一个方法调用中返回整个结果集?

类似问题:

存在许多类似的问题,其中有人询问分页(意味着从 LDAP 服务器到应用程序服务器),并得到涉及 PageSize 和 SizeLimit 的响应。但是,这些属性仅影响 C# 服务器和 LDAP 服务器之间的分页,最终,DirectorySearch 唯一相关的方法是 FindOne() 和 FindAll()。

我正在寻找的基本上是“FindPaged(pageSize, pageNumber)”(pageNumber是真正重要的位。我不仅仅想要前1000个结果,我想要(例如)第100组1000个结果应用程序无法等待 100,000 条记录从 LDAP 服务器传递到应用程序服务器,即使它们被分成 1,000 条记录块

。了解 DirectoryServices.Protocols 有 SearchRequest,它(我认为?)允许您使用“PageResultRequestControl”,它看起来像我正在寻找的东西(尽管它看起来像分页信息来自“cookies”,我不知道我应该如何检索)但如果有一种方法可以做到这一点而不用重写整个协议来代替,我宁愿不必这样做,

我只是无法想象没有 。这样做的方法...甚至 SQL 也有

UPDATE: PageResultRequestControl 没有帮助 - 它是只向前和顺序的(您必须调用并获取前 N 个结果,然后才能获取调用获取结果 N+1 所需的“cookie”令牌)。

然而,cookie 似乎确实具有某种可重现的排序...在我正在处理的结果集上,我逐一迭代结果,每次 cookie 都会这样出现:

1: {8, 0, 0, 0}
2: {11, 0, 0, 0}
3: {12, 0, 0, 0}
4: {16, 0, 0, 0}

当我两两迭代时,我得到相同的数字 (11, 16)。 这让我想到,如果我能弄清楚如何生成这些数字的代码,我就可以创建一个临时 cookie,这将准确地为我提供我正在寻找的分页。

I am working in C#, and am trying to use DirectorySearch to query the groups of an extremely large Microsoft ActiveDirectory LDAP server.

So, in my application, I'm going to have a paged list of groups, with searching capability. Naturally, I don't want to hammer my LDAP server with passing me the entire result set for these queries every time I hit "Next Page".

Is there a way, using DirectorySearch, to retrieve ONLY a single arbitrary page's results, rather than returning the entire result-set in one method call?

Similar questions:

Many questions like these exist, where someone asks about paging (meaning from LDAP server to app server), and gets responses involving PageSize and SizeLimit. However, those properties only affect paging between the C# server and the LDAP server, and in the end, the only relevant methods that DirectorySearch has are FindOne() and FindAll().

What I'm looking for is basically "FindPaged(pageSize, pageNumber)" (the pageNumber being the really important bit. I don't just want the first 1000 results, I want (for example) the 100'th set of 1000 results. The app can't wait for 100,000 records to be passed from the LDAP server to the app server, even if they are broken up into 1,000-record chunks.

I understand that DirectoryServices.Protocols has SearchRequest, which (I think?) allows you to use a "PageResultRequestControl", which looks like it has what I'm looking for (although it looks like the paging information comes in "cookies", which I'm not sure how I'd be supposed to retrieve). But if there's a way to do this without rewriting the entire thing to use Protocols instead, I'd rather not have to do so.

I just can't imagine there's no way to do this... Even SQL has Row_Number.

UPDATE:
The PageResultRequestControl does not help - It's forward-only and sequential (You must call and get the first N results before you can get the "cookie" token necessary to make a call to get result N+1).

However, the cookie does appear to have some sort of reproducible ordering... On a result set I was working on, I iterated one by one through the results, and each time the cookie came out thusly:

1: {8, 0, 0, 0}
2: {11, 0, 0, 0}
3: {12, 0, 0, 0}
4: {16, 0, 0, 0}

When I iterated through two by two, I got the same numbers (11, 16).
This makes me think that if I could figure out the code of how those numbers are generated, I could create a cookie ad-hoc, which would give me exactly the paging I'm looking for.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

久伴你 2024-12-15 07:43:51

PageResultRequestControl 确实是执行此操作的方法,它是 LDAP 协议的一部分。您只需要弄清楚这对您的代码意味着什么,抱歉。应该有一种方法可以从您所在的地方使用它,但是,话虽如此,我正在使用 Java 工作,我只需要编写十几个请求控件和扩展操作类以便与 JNDI 一起使用,这样您就可以可能不走运……或者你可能不得不像我一样。警告,ASN.1 解析紧随其后:-|

The PageResultRequestControl is indeed the way to do this, it's part of the LDAP protocol. You'll just have to figure out what that implies for your code, sorry. There should be a way to use it from where you are, but, having said that, I'm working in Java and I've just had to write a dozen or so request controls and extended-operation classes for use with JNDI so you might be out of luck ... or you might have to do like I did. Warning, ASN.1 parsing follows not that far behind :-|

淡淡绿茶香 2024-12-15 07:43:51

遗憾的是,鉴于当前的 C# 库,似乎没有办法做到这一点。

所有标准 C#4.0 LDAP 库都返回前 N 个结果(如 FindAll(),它返回每个结果,FindOne(),它返回第一个结果,或者 SearchResult 和 PageResultRequestControl,它返回结果 N 到 N+M但要求您先检索结果 1 到 N-1,然后才能获得可与请求一起传递的 cookie 令牌,以便获取下一组结果。

我找不到任何允许的第三方 LDAP 库。这个,除非

。 ,我的前进方向将是修改界面以显示前 X 个结果,没有客户端分页功能(显然仍然适当地使用服务器端分页)。

找到更好的解决方案后 稍后,通过将更新的 cookie 与响应一起传递给客户端,然后通过单击“更多结果”类型的按钮将其传回。
不管这些饼干是否可以手工制作,以后可能值得追求。

更新:
我与 Microsoft 支持人员交谈并确认了这一点 - 无法使用 LDAP 服务器进行动态分页。这是 LDAP 服务器本身的限制。

你可以使用Protocols和Paging控件(如果你的LDAP服务器支持的话)随意前进,但是cookie没有跨服务器(甚至跨版本)标准,所以你无法合理地制作自己的,并且不能保证 cookie 可以重复用于重复查询。

完整的解决方案涉及使用协议(如上所述的分页)将可分页结果集拉入 SQL,无论是临时表还是永久存储表,并允许用户以传统方式对该结果集进行分页和排序。请记住,您的结果不会完全是最新的,但通过一些智能缓存更新,您可以最大限度地降低这种风险。

Sadly, it appears there may not be a way to do this given current C# libraries.

All of the standard C#4.0 LDAP libraries return Top-N results (As in, FindAll(), which returns every result, FindOne(), which returns the first result, or SearchResult with PageResultRequestControl, which returns results N through N+M but requires you to retrieve results 1 through N-1 before you'll have a cookie token that you can pass with the request in order to get the next set.

I haven't been able to find any third-party LDAP libraries that allow this, either.

Unless a better solution is found, my path forward will be to modify the interface to instead display the top X results, with no client paging capabilities (obviously still using server-side paging as appropriate).

I may pursue a forward-only paging system at a later date, by passing the updated cookie to the client with the response, and passing it back with a click of a "More Results" type of button.
It might be worth pursuing at a later date, whether or not these cookies can be hand-crafted.

UPDATE:
I spoke with Microsoft Support and confirmed this - There is no way to do dynamic paging with LDAP servers. This is a limitation of LDAP servers themselves.

You can use Protocols and the Paging control (if your LDAP server supports it) to step forward at will, but there is no cross-server (or even cross-version) standard for the cookie, so you can't reasonably craft your own, and there's no guarantee that the cookie can be reused for repeated queries.

A full solution involves using Protocols (with Paging as above) to pull your pageable result set into SQL, whether into a temp table or a permanent storage table, and allow your user to page and sort through THAT result set in the traditional manner. Bear in mind your results won't be precisely up to date, but with some smart cache updating you can minimize that risk.

终陌 2024-12-15 07:43:51

也许您想相应地使用范围属性迭代您的“页面”:

----copy & Paste----

此示例检索条目 0-500(含)。

DirectoryEntry group = new DirectoryEntry("LDAP://CN=Sales,DC=Fabrikam,DC=COM");
DirectorySearcher groupMember = new DirectorySearcher
    (group,"(objectClass=*)",new string[]{"member;Range=0-500"},SearchScope.Base);
SearchResult result = groupMember.FindOne();
// Each entry contains a property name and the path (ADsPath).
// The following code returns the property name from the PropertyCollection. 
String propName=String.Empty;
foreach(string s in result.Properties.PropertyNames)
{
    if ( s.ToLower() != "adspath")
    {
      propName = s;
      break;
    }
}
foreach(string member in result.Properties[propName])
{
     Console.WriteLine(member);
}

----复制&粘贴----

更多信息请参阅:

枚举大组中的成员
https://msdn.microsoft.com/en-us/library/ms180907。 aspx

属性值的范围检索
https://msdn.microsoft.com/en-us/library/cc223242。 aspx

使用范围检索进行搜索
https://msdn.microsoft.com/en-us/library/aa367017。 ASPX

Maybe you want to iterate through your "pages" using the range-attribute accordingly:

----copy & paste----

This sample retrieves entries 0-500, inclusively.

DirectoryEntry group = new DirectoryEntry("LDAP://CN=Sales,DC=Fabrikam,DC=COM");
DirectorySearcher groupMember = new DirectorySearcher
    (group,"(objectClass=*)",new string[]{"member;Range=0-500"},SearchScope.Base);
SearchResult result = groupMember.FindOne();
// Each entry contains a property name and the path (ADsPath).
// The following code returns the property name from the PropertyCollection. 
String propName=String.Empty;
foreach(string s in result.Properties.PropertyNames)
{
    if ( s.ToLower() != "adspath")
    {
      propName = s;
      break;
    }
}
foreach(string member in result.Properties[propName])
{
     Console.WriteLine(member);
}

----copy & paste----

for more Information see:

Enumerating Members in a Large Group
https://msdn.microsoft.com/en-us/library/ms180907.aspx

Range Retrieval of Attribute Values
https://msdn.microsoft.com/en-us/library/cc223242.aspx

Searching Using Range Retrieval
https://msdn.microsoft.com/en-us/library/aa367017.aspx

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文