2
Vote

Fixing slow query speed, Guid Filter and DateTime mapping (on linqtoad-12012.zip)

description

Introduction:

 
First let me thank the author of this library. I am only starting to learn linq for the last three days. I am really fascinated and thinking of moving to .NET 3.5 because of this (I have to develop an extensive data driven application). I read book chapters and looked online for examples. I was also seeking ways to integrate LDAP to linq and found this site. Out of the box, the code worked for me (just replaced the ROOT location to point to my AD).
 
 

Problem:

 
While using this library (Version/Name of package: linqtoad-12012.zip), I immediately encountered the following problems:
  1. SLOW: The Performance was very slow. I ran the query on an OU that returned 567 users. But this was very slow and the operation to convert to an arraylist took 34 seconds (average).
  2. GUID SEARCH: I can get the GUID field for a user, but when I search by GUID to locate a user, the query fails.
  3. DATETIME FIELD: When I map a DateTime Field for example pwdLastSet, I cannot assign DateTime type.
            a.   I have two options:
                             i. Use the NativeObject mapping as author suggested see below:
                                                      [DirectoryAttribute("PasswordLastChanged", DirectoryAttributeType.ActiveDs)]
                                                      public DateTime PasswordLastSet { get; set; }
                             ii.    Use long as the data type and use a typecasting/conversion during every use.
             b. But I can’t do the following:
                                     [DirectoryAttribute("PwdLastSet")]
                                     public DateTime PasswordLastSet { get; set; }
             c. This is not to say that the authors approach is wrong. It is infact correct. It uses ActiveDs helper object to map the datatype correctly. But the problem is speed (our problem 1). Calls to DirectoryEntry.NativeObject is slow.
     
     

Solution:

A Solution to these problems is attached (just replace the DirectorySource.cs file of package :
Readers should be aware that my understanding of LINQ is really shady at the moment. I barely have a working knowledge. I just tested my solution driven by my own need for speed, but it may as well break some functionality. So, please test the code before and after you replace the module DirectorySource.cs in linqtoad-12012.zip).
In the attached code you will find a comment with my name wherever I have applied a change. For example:
// ****** Code Modified (Commented by: Russel Ahmed Apu, russel_ahmed_apu @ hotmail dot com) *********
// Disable this because we dont want to call GetDirectoryEntry() if we dont need it
//DirectoryEntry e = sr.GetDirectoryEntry();
// ******************************** END Of Modification *****************************************
 
So, if you don’t want a certain change you can certainly go back to the old code. Please use your judgment and always test your code.

USING THE CHANGES PROPOSED BELOW,
I MANAGED TO SPEEDUP A QUERY THAT TOOK 34 SECONDS
TO 0.25 SECONDS!!!

Also, I can now map DateTime and Guid fields accordingly.
I can also search by guid objects, like this:
In Entity.cs
~~~~~~~~~~~~~~~~~~~~~~~~~~
...
[DirectoryAttribute("objectGUID")]
public Guid Id { get; set; }
[DirectoryAttribute("PwdLastSet")]
public DateTime PasswordLastSet { get; set; }
...
In Program.cs
~~~~~~~~~~~~~~~~~~~~~~~~~~
...
Guid myguid = new Guid("39267f96-e560-49dc-884c-4f036f78be0b");
var AllUsers = from usr in dtx.Canada.Users where usr.ObjectCategory == "Person" && usr.Id==myguid select usr;
foreach (var u in AllUsers)
{
Console.WriteLine("{0} - {1}",u.Name, u.Id);
}
...
 
 

Explanation For Speedup:

The reason for this slow speed is the call to SearchResult.GetDirectoryEntry(). This method is called from Method GetResults() and AssignResultPropery() methods implemented by the original author. The AD GetDirectoryEntry is called to retrieve every single property, so it’s called many times for each query row.
To resolve this issue, I took an alternative track. I initialized the DirectorySearcher object by adding s.PropertiesToLoad.Add(…) method calls for every properties that must be extracted from AD. I removed calls to GetDirectoryEntry whenever possible and instead used SearchResult.Properties[] to get the property values directly from the SearchResult object. This makes information retrieval very fast.
The only places where GetDirectoryEntry is needed is when you want to apply changes to certain objects and need to map properties using the ActiveDs helper object (i.e. PasswordLastChanged). Thus, if you can avoid nativeobject, this MOD will be very fast (It will be slower for updates).

file attachments

comments

lookitstony wrote Jan 8, 2010 at 5:47 PM

Thanks! I just implemented all the changes. My site still works! Thanks!

wrote Jul 18, 2010 at 10:56 AM

wrote Feb 14, 2013 at 6:56 PM