Sunday, January 9, 2011

LINQ To LDAP: How Does It Work Part 1

UPDATE: Query methods have been reduced to encourage manual mapping for non-anonymous types.
UPDATE: root has been renamed to namingContext

So in my last post I had two examples showing Linq to LDAP working. I want to cover how it all works. I'll start with the interface IDirectoryContext:

public interface IDirectoryContext : IDisposable
{
    IQueryable<T> Query<T>() where T : class;
    IQueryable<T> Query<T>(SearchScope scope) where T : class;
    IQueryable<T> Query<T>(T example, string namingContext) where T : class;
    IQueryable<T> Query<T>(T example, string namingContext, string objectCategory) where T : class;
    IQueryable<T> Query<T>(T example, SearchScope scope, string namingContext) where T : class;
    IQueryable<T> Query<T>(T example, SearchScope scope, string namingContext, string objectCategory) where T : class;
}

The available parameters:
  • example: This as an anonymous object that can be used for auto mapping. In my previous post my anonymous object looked like this:
    var example = new {DistinguishedName = "", Cn = ""};
       
    All you need is to specify a name and a value so the compiler can infer the type. Here's an example with more properties:
    var example =
        new
            {
                DistinguishedName = "",
                Cn = "",
                WhenCreated = default(DateTime),
                ObjectGuid = default(Guid),
                DirectReports = default(string[])
            };
       
    Auto mapped properties must have names that match the directory attribute name. Casing does not matter.
  • scope: This determines the depth at which the search is performed. You can read more about search scopes here. I always default to a subtree scope if you don't specify one.
  • namingContext: This is the place in the directory from which you want to start your search. You can make it the root of the directory "DC=Northwind,DC=local" or you can go deeper "CN=Users,CN=Employees,DC=Northwind,DC=local". You'll notice that if you query by example, you must always specify the naming context. I do this because auto mapping cannot infer the naming context.
  • objectCategory: This is an LDAP attribute you can specify to improve searching performance. You may be wondering why I use objectCategory instead of objectClass. It boils down to objectCategory being single valued and objectClass being multivalued so searching by objectCategory is faster. You can read more about it here.

2 comments:

  1. Speaking of "Query by Example", could you explain in what scenario would a developer use QBE to run a query against LDAP?

    ReplyDelete
  2. When I originally added QBE, there was no method for dynamic querying. I intended it to be used for simple queries for specific data. However, I added IDirectoryAttributes in 2.0 and I believe that is at least on par with QBE today. It's pretty much a matter of preference now.

    ReplyDelete