Click here to Skip to main content
Click here to Skip to main content

Typed LDAP Queries

, 12 Nov 2008 CPOL
Rate this:
Please Sign up or sign in to vote.
Dynamically generating well formed LDAP queries using managed code.

Introduction

Writing queries using Lightweight Directory Access Protocol (LDAP) has always been challenging, especially when you are not used to the LDAP syntax. The inclusion of the System.DirectoryServices namespaces in the .NET framework made writing code for LDAP libraries a lot easier than with the traditional Active Directory Services Interfaces (ADSI) in non-managed languages. However, search functions in this namespaces such as the DirectorySearcher class still relies on the ability of the programmer to write LDAP queries properly, thus leaving the fate of a well formatted query on the hands of the runtime.

A More Structured Solution

After analyzing and looking for a more structured way of writing these types of queries, I found a very compelling and clever way of writing function statements with conditional logic, which I found in Microsoft Excel. Excel’s way of writing functions consists of defining the logical operator as the function and the members inside the function on which they operate. For instance, consider the following query:

Select car from cars where (car.color = colors.red OR car.color = colors.blue) 
  AND car.make = makes.ford AND car.passengers > 5 AND car.model >= 2008

It can be also expressed as:

AND(
   OR(
      EQUALTO(car.color, colors.red), 
      EQUALTO(car.color, colors.blue)), 
   EQUALTO(car.make, makes.ford), 
   GREATHERTHAN(car.passengers, 5), 
   OR(
      GREATHERTHAN(car.model, 2008),
      EQUALTO (car.model, 2008))

In LDAP, the query would be as follows:

(&( |((color=red)(color=blue))(make=ford)(passengers>5)(model>=2008) ))

You can see how similar the last two expressions are.

Search Criteria

The first thing we need is a helper class to define expressions using syntax like the above. The SearchCriteria class easily allows to define queries of this type, as defined below:

public class SearchCriteria
{
   public SearchCriteria<T>[] Criteria { get; set; }
   public static AndCriteria And(params SearchCriteria<T>[] criteria)
   public static OrCriteria Or(params SearchCriteria<T>[] criteria)
   public static NotCriteria Not(SearchCriteria<T> criteria)
   public static GreatherThanFunctionCriteria GreatherThan(T name, string value)
   public static LessThanFunctionCriteria LessThan(T name, string value)
   public static EqualToFunctionCriteria EqualTo(T name, string value)
   public static ContainsFunctionCriteria Contains(T name, string value)
   public static IsLikeFunctionCriteria IsLike(T name, string value)
}

Then, to define the car query from the example above, we have to define an enumeration for fields allowed for the element car, as follows:

public enum Car { color, make, passengers, model, } 

Typed LDAP

Here is how we express the query in managed code:

var expression = SearchCriteria<Car>.And( 
   SearchCriteria<Car>.Or( 
      SearchCriteria<Car>.EqualTo(Car.color, Colors.red.ToString()), 
      SearchCriteria<Car>.EqualTo(Car.color, Colors.blue.ToString())), 
   SearchCriteria<Car>.EqualTo(Car.make, Makes.ford.ToString()), 
   SearchCriteria<Car>.GreatherThan(Car.passengers, "5"), 
   SearchCriteria<Car>.Or( 
      SearchCriteria<Car>.GreatherThan(Car.model, "2008"),  
      SearchCriteria<Car>.EqualTo(Car.model, "2008")));

Once we have a criteria object, we can pass that to the LdapBuilder engine, which is another static class with one method:

public static string GetLdap(SearchCriteria criteria)
...
string ldapQuery = LdapBuilder<Car>.GetLdap(expression);

Then, invoking this method will dynamically call the proper routines that will generate a string representing a well formed LDAP query, that simple!

The Sample Code

In the sample code, you will find a fully functional version of this engine along with the implementation of the car example used in this article. Enjoy it Smile | :)

TypedLdapTestForm.jpg

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

Share

About the Author

luis_botero
Software Developer (Senior)
United States United States
Born and built for Software Development. Eager to develop systems that drive business and human intelligence to the next level. Love Artificial Intelligence and have abundant experience in developing systems with a large user base. I know more than just how to write code that compiles. I can produce software that is fast, reliable, well-tested, secure, maintainable, globalizable, and on down the list of attributes of high-quality code.

Comments and Discussions

 
GeneralMy vote of 5 PinprofessionalAmir Mohammad Nasrollahi7-Aug-13 23:12 
GeneralLDAP Criteria PinmemberCubaman19-Nov-08 8:18 
GeneralExcellent idea Pinmemberrht34116-Nov-08 5:19 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.1411023.1 | Last Updated 12 Nov 2008
Article Copyright 2008 by luis_botero
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid