Reputation: 4640
I have a code which either gets 1000 or all the results using DirectorySearcher
.
But I want to get only 2000 of 6000 results.
Here is the code to get 6000 results whereas I only want 2000
mySearcher.SizeLimit = 2000;
mySearcher.PageSize = 1000;
SearchResultCollection results = mySearcher.FindAll();
int totalUsers = results.Count;
Please help.
Thanks
My research says PageSize = 0 gives 1000 results only and Pagesize = 1000 gives all results.
Need more help to make this work.
Upvotes: 2
Views: 9593
Reputation: 5681
According to this post: DirectorySearcher.FindAll() - should have PageSize=1000
SizeLimit
doesn't matter in this case as the Server side default is being used which defaults to 1000 results. I've never needed to page like this but I imagine the minimum size limit is used (between your size limit and server size limit - just tested it in my own AD). Your PageSize
is indeed paging however it does the paging in the background and returns you only the final stream as I understand which is why you are getting all results.
I believe your easiest solution is to just use Linq on top of this and do a .Take(2000)
on results. This would get you your desired result at the cost of additional bandwidth and processing on server.
If you really want to sort that, I guess you will have to go update the servers default paging size to be higher (though i doubt this will be feasible for administrative reasons).
EDIT:
Here is how I'd go about this roughly (quick working sample code from my LinqPad - also note that I'm actually bringing over everything unlike how you might wanna do this by taking the for loop out of equation):
using(DirectoryEntry de = new DirectoryEntry("LDAP://domain.local/dc=domain,dc=local", "user", "password"))
using(DirectorySearcher ds = new DirectorySearcher(de))
{
ds.Filter="(&(objectCategory=user)(objectClass=user))";
ds.PageSize= 1000;
ds.PropertiesToLoad.Clear();
ds.PropertiesToLoad.Add("objectGuid");
var results = ds.FindAll();
var searchResults = results.Cast<System.DirectoryServices.SearchResult>().ToArray();
int myDesiredPageSize = 2000;
var upns = new StringCollection();
for(var step=0; step < Math.Ceiling((double)results.Count / myDesiredPageSize); step++)
{
Parallel.ForEach(searchResults.Skip(step*myDesiredPageSize).Take(myDesiredPageSize), result => {
using(var entry = result.GetDirectoryEntry())
{
entry.RefreshCache(new[]{ "userPrincipalName" });
if(entry.Properties.Contains("userPrincipalName"))
upns.Add(entry.Properties["userPrincipalName"][0] as string);
}
});
}
upns.Count.Dump();
}
This returns about 1400 results in about 3 seconds over my lan connection in my test scenario. Since we are querying in parallel higher numbers should not scale linearly. Also you may want to contain the parallelisation to some degree as this would hammer AD mercilessly :)
In my normal operations, I employ caching with WhenChanged
attribute of AD objects to reduce my actual querying to only changed objects instead of loading the same thing over and over which only takes the hit first time around and subsequent results are fraction of a second. Taking this approach you can do away with paging entirely and just load your properties when you start and then pull only the changed entries if that is an option.
Upvotes: 2
Reputation: 28325
There seems to be a slight weird behavior with the PageSize
property.
Please set it to 0
, does that work?
By the way:
c# Active Directory Services findAll() returns only 1000 entries
Can I get more than 1000 records from a DirectorySearcher in Asp.Net?
Upvotes: 2