Tuesday, February 1, 2011

LINQ To LDAP: How Does It Work Part 2

So up until this point all of my posts have used the auto-mapping via anonymous types. For this post I want to cover manual mapping of classes.

Here is an example mapping:

public class User
{
    public string DistinguishedName { get; set; }
    public int BadPasswordCount { get; set; }
    public string[] Employees { get; set; }
    public string Title { get; set; }
    public string PostalCode { get; set; }
    public string CommonName { get; set; }
    public DateTime? WhenCreated { get; set; }
    public string FirstName { get; set; }
    public Guid Guid { get; set; }
    public string City { get; set; }
    public int Version { get; set; }
    public string Country { get; set; }
    public DateTime? LastChanged { get; set; }
    public byte[] Sid { get; set; }
    public long EmployeeId { get; set; }
    public string PhoneNumber { get; set; }
    public string Street { get; set; }
    public string Comment { get; set; }
    public string Name { get; set; }
    public string LastName { get; set; }
}

public class UserMapping : ClassMap<User>
{
    public UserMapping()
    {
        NamingContext("CN=Users,CN=Employees,DC=Northwind,DC=local");
        ObjectCategory("person");

        Map(u => u.BadPasswordCount).Named("badpwdcount");
        Map(u => u.Employees).Named("directreports");
        Map(u => u.Title);
        Map(u => u.PostalCode);
        Map(u => u.CommonName).Named("cn");
        Map(u => u.WhenCreated);
        Map(u => u.FirstName).Named("givenname");
        Map(u => u.Guid).Named("objectguid");
        Map(u => u.City).Named("l");
        Map(u => u.Version).Named("usnchanged");
        Map(u => u.Country).Named("c");
        Map(u => u.LastChanged).Named("whenchanged");
        Map(u => u.Sid).Named("objectsid");
        Map(u => u.DistinguishedName);
        Map(u => u.EmployeeId);
        Map(u => u.PhoneNumber).Named("telephonenumber");
        Map(u => u.Street);
        Map(u => u.Comment);
        Map(u => u.Name);
        Map(u => u.LastName).Named("sn");
    }
}

I specify the object's location in the directory by using NamingContext(). I also map it to a object category, but it's not required. Mapping properties is pretty straightforward. You use a lambda expression to map a property and if it has a different name in the directory then you can specify that with Named().

It's not always necessary to create a specific mapping for your classes. The same way auto-mapping works with anonymous types, you can use the class as an example and it will map everything by convention. You have two options if you want to auto-map an existing class:

//Option 1
var user = context.Query<User>("CN=Users,CN=Employees,DC=Northwind,DC=local")
                .FirstOrDefault(u => u.Name == "Alan Hatter");

//Option 2
var example = new User();
var user = context.Query(example, "CN=Users,CN=Employees,DC=Northwind,DC=local", "Person")
                .FirstOrDefault(u => u.Name == "Alan Hatter");

If you try to auto-map an existing class without specifying a namingContext, you will get a MappingException. Also, remember your property names have to match the names in the directory for everything to work with auto-mapping. I'll cover finding available attributes, their types, and names in my next post. Stay tuned!

3 comments:

  1. He encontrado este blog por la búsqueda de LINQ to LDAP. Esto es muy interesante y me encuentro con su código muy sorprendente. Por favor, mantenga el buen trabajo y hacer que el código mucho para todos nosotros para ver.

    ReplyDelete
  2. Thanks for the support! The source code is hosted at codeplex as LINQ to LDAP. I'm hoping to have a 1.0 version ready in the next few weeks.

    ReplyDelete