Wednesday, November 24, 2010

LINQ To LDAP: Referential Integrity

I'm using the Northwind sample database to populate employees in Lightweight Directory Services.  I ran into an issue when trying to populate managers.  I incorrectly assumed that I could add employees in any order as long as I had a well formatted distinguished name for the manager.  Apparently some reference checking was being done behind the scenes for manager because I was getting a constraint error.  So a little refactoring and everything works!  Also, if no value exists for referenced entries, you can't just supply a null and call it good.  You have to opt out of sending that value or you'll get a null value error.

private void AddEmployee(LdapConnection connection, Employee employee)
{
    var distinguishedName = "CN=" + 
        employee.FirstName + " " + employee.LastName + 
        ",CN=Users,CN=Employees,DC=Northwind,DC=local";

    addedEmployees.Add(employee.EmployeeID, distinguishedName);

    string managerDistinguishedName = 
        employee.Manager == null 
            ? null
            : addedEmployees[employee.Manager.EmployeeID];

    List<DirectoryAttribute> attributes =
        new List<DirectoryAttribute>
            {
                new DirectoryAttribute("employeeID", employee.EmployeeID.ToString()),
                new DirectoryAttribute("sn", employee.LastName),
                new DirectoryAttribute("givenName", employee.FirstName),
                new DirectoryAttribute("comment", employee.Notes),
                new DirectoryAttribute("telephoneNumber", employee.HomePhone),
                new DirectoryAttribute("photo", employee.Photo),
                new DirectoryAttribute("title", employee.Title),
                new DirectoryAttribute("street", employee.Address),
                new DirectoryAttribute("l", employee.City),
                new DirectoryAttribute("c", employee.Country),
                new DirectoryAttribute("postalCode", employee.PostalCode)
            };
    if (!string.IsNullOrEmpty(managerDistinguishedName))
    {
        attributes.Add(
            new DirectoryAttribute("manager", managerDistinguishedName));
    }

    AddRequest addRequest = new AddRequest(distinguishedName, "user");
    addRequest.Attributes.AddRange(attributes.ToArray());
    connection.SendRequest(addRequest);

    if (employee.Employees.Any())
    {
        foreach (var subordinate in employee.Employees)
        {
            AddEmployee(connection, subordinate);
        }
    }
}