I have a query against an LDAP server in my code which grabs a particular list of employees for the user to choose from but takes 20-30 seconds to execute. The list changes as employees leave/join which might happen, say, roughly 3 times a year but I need the
list to be current. My solution has been to have an XML file which acts as a quick access buffer to reduce this delay with LDAP. To update the list the user has to click a button which executes the query and overwrites the XML file. They only do this if they
cannot find the employee in the list. Can I automate this process to occur on a regulated basis? Ideally this should be outside of any user sessions and so prevent the user experiencing this delay or having to click the button to update. Cheers
I can think of a couple easy things for you to try: 1. Cache the query results. You can do this after the first request or in your Global.asax on Application Start. From then on, it will be extremely fast and available as long as your application is. 2. Speed
up your search by using indexes. This requires changing the Schema a little bit, but if you are using this search or similar searches a lot, it is appropriate to do. Done properly this can produce a many-fold speed increase. What is the filter you are using?
I might be able to tell if it is appropriate for indices.
Thanks for the suggestions. Here is my LDAP code... the users are filtered based on whether they are from a certain section of the organisation (XYZ) and I parse adspath from all those users to make sure they are staff members as opposed to other members from
that section. An example of the adspath would be: LDAP://servername/cn=Z0000636,ou=xyzstaff,ou=XYZ,o=myorg or LDAP://servername/cn=Z0000634,ou=xyznonstaff,ou=XYZ,o=myorg By the way, the xml file way works fast enough but it would be good to do the LDAP query
either more quickly on every user request, or on a nightly basis away from users sessions if this cannot be achieved. For the latter I think I need to use the Scheduled Tasks on Windows and get the Server's OS to run a console app with the query, but I'm open
to the indexing idea if you can help me out. Cheers.
try
{
string path = ConfigurationSettings.AppSettings["LDAPServer"];
DirectoryEntry entry = new DirectoryEntry(path);
DirectorySearcher searcher = new DirectorySearcher(entry);
searcher.Filter = "(ou=XYZ)";
searcher.PropertiesToLoad.Add("givenname");
searcher.PropertiesToLoad.Add("sn");
searcher.PropertiesToLoad.Add("adspath");
SearchResultCollection results = searcher.FindAll();
foreach(SearchResult resEnt in results)
{
ResultPropertyCollection propColl = resEnt.Properties;
// set up variables for use in one loop
string firstName = "";
string lastName = "";
int staffIndx = 0;
string staffNumber = "";
foreach(string key in propColl.PropertyNames)
{
if("givenname" == key)
{
foreach(object values in propColl[key])
{
firstName = values.ToString().Trim();
}
}
if("sn" == key)
{
foreach(object values in propColl[key])
{
lastName = values.ToString().Trim();
}
}
if ("adspath" == key)
{
foreach(object values in propColl[key])
{
//take value and check contents
string valString = values.ToString();
//"XYZ staff" check
staffIndx = valString.IndexOf("xyzstaff");
int startNum = valString.IndexOf("cn=") + 3;
int length = valString.IndexOf(",") - startNum;
staffNumber = valString.Substring(startNum, length);
}
}
}
//if staff member from XYZ, add to data table (before sorting)
if (staffIndx > 0)
{
DataRow newRow;
newRow = dtSCMStaff.NewRow();
newRow["FirstName"] = firstName;
newRow["LastName"] = lastName;
newRow["StaffNumber"] = staffNumber;
dtXYZStaff.Rows.Add(newRow);
}
}
}
catch
{
lblInstructions.Text = "There was a problem with accessing the LDAP server."
}
Maybe I am being simplistic, but you want to search for all users in an OU called 'XYZ'. The filter you are using, "(OU=XYZ)" suprises me that it works honestly. That filter says search for all objects that have an
attribute called 'OU' that is equal to XYZ. That is a lot different than saying, search for all objects
in an OU called XYZ. Correct me if I am wrong, but you have two OUs ('xyzstaff', and 'xyznonstaff') as child OUs under another OU ('xyz'). Why don't you base your search from the 'xyzstaff' OU instead of the 'xyz' OU and you will not have to parse any
results to see if they are staff or not (since the location is different). If you are willing to try, there is a function that I shared awhile ago that might come in handy here: 163706. This function (called FindUsers()) returns a DataSet based on an LDAP
query. In your situation, you would use it like this:
Now, the 'ds' would hold a table of users from the 'xyzstaff' OU. Furthermore it would be cached until people stopped using it for a set period of time. So, then next time someone requests it, it would
be pretty much instant. You can see the code in the post, and change the time period if you would like or set it to never.
If you can, implement indexes for the attributes you are searching on. We just got thru adding this and it dramatically improved the performance. It really was shocking how much faster it was once the indexes were built. hope this helps, lee franke
Hi, Believe it or not, I didn't even realise that you could search against the server like that. The query is now done in a second which is great. I'll try and integrate with the dataset generating code too. Caching would make things even better I'm sure so
I'll follow that lead. What do you think of
this book to get me up to speed with the technology? Cheers.
calcium
Member
600 Points
121 Posts
Slow LDAP query workaround
Jan 21, 2004 03:07 PM|LINK
Voldo
Member
145 Points
29 Posts
Re: Slow LDAP query workaround
Jan 22, 2004 03:25 AM|LINK
calcium
Member
600 Points
121 Posts
Re: Slow LDAP query workaround
Jan 22, 2004 08:22 AM|LINK
dunnry
Star
9098 Points
1806 Posts
Re: Slow LDAP query workaround
Jan 22, 2004 02:30 PM|LINK
Weblog
The Book
LDAP Programming Help
calcium
Member
600 Points
121 Posts
Re: Slow LDAP query workaround
Jan 23, 2004 09:19 AM|LINK
try { string path = ConfigurationSettings.AppSettings["LDAPServer"]; DirectoryEntry entry = new DirectoryEntry(path); DirectorySearcher searcher = new DirectorySearcher(entry); searcher.Filter = "(ou=XYZ)"; searcher.PropertiesToLoad.Add("givenname"); searcher.PropertiesToLoad.Add("sn"); searcher.PropertiesToLoad.Add("adspath"); SearchResultCollection results = searcher.FindAll(); foreach(SearchResult resEnt in results) { ResultPropertyCollection propColl = resEnt.Properties; // set up variables for use in one loop string firstName = ""; string lastName = ""; int staffIndx = 0; string staffNumber = ""; foreach(string key in propColl.PropertyNames) { if("givenname" == key) { foreach(object values in propColl[key]) { firstName = values.ToString().Trim(); } } if("sn" == key) { foreach(object values in propColl[key]) { lastName = values.ToString().Trim(); } } if ("adspath" == key) { foreach(object values in propColl[key]) { //take value and check contents string valString = values.ToString(); //"XYZ staff" check staffIndx = valString.IndexOf("xyzstaff"); int startNum = valString.IndexOf("cn=") + 3; int length = valString.IndexOf(",") - startNum; staffNumber = valString.Substring(startNum, length); } } } //if staff member from XYZ, add to data table (before sorting) if (staffIndx > 0) { DataRow newRow; newRow = dtSCMStaff.NewRow(); newRow["FirstName"] = firstName; newRow["LastName"] = lastName; newRow["StaffNumber"] = staffNumber; dtXYZStaff.Rows.Add(newRow); } } } catch { lblInstructions.Text = "There was a problem with accessing the LDAP server." }dunnry
Star
9098 Points
1806 Posts
Re: Slow LDAP query workaround
Jan 23, 2004 03:35 PM|LINK
string qry = "(&(objectClass=user)(objectCategory=person))"; string[] columns = new string[]{"givenName", "sn", "adsPath"}; string ldapPath = "LDAP://servername/ou=xyzstaff,ou=XYZ,o=myorg"; DataSet ds = FindUsers(qry, columns, ldapPath, true);>Now, the 'ds' would hold a table of users from the 'xyzstaff' OU. Furthermore it would be cached until people stopped using it for a set period of time. So, then next time someone requests it, it would be pretty much instant. You can see the code in the post, and change the time period if you would like or set it to never.Weblog
The Book
LDAP Programming Help
leefranke
Member
430 Points
90 Posts
Re: Slow LDAP query workaround
Jan 23, 2004 07:56 PM|LINK
calcium
Member
600 Points
121 Posts
Re: Slow LDAP query workaround
Jan 26, 2004 08:02 AM|LINK