Project Description
LINQ provider built on top of System.DirectoryServices.Protocols for querying and updating LDAP servers.

NuGet Package

Features

  • Translates lamda expressions into LDAP filters according to RFC4515.
  • Map POCOs to directory objects.
  • Ad hoc querying using anonymous types or custom DirectoryAttributes class.
  • Fluent mapping and configuration.
For more features see the Documentation

C# Mapped Objects

[DirectorySchema("CN=Users,CN=Employees,DC=Northwind,DC=local", ObjectClass = "User")]
public class User : DirectoryObjectBase
{
    [DistinguishedName]
    public string DistinguishedName { get; set; }

    [DirectoryAttribute("cn", ReadOnly = true)]
    public string CommonName { get; set; }

    [DirectoryAttribute]
    public string Title { get; set; }

    [DirectoryAttribute(StoreGenerated = true)]
    public Guid ObjectGuid { get; set; }

    [DirectoryAttribute(StoreGenerated = true)]
    public SecurityIdentifier ObjectSid { get; set; }

    [DirectoryAttribute(StoreGenerated = true)]
    public DateTime WhenChanged { get; set; }
}

var config = new LdapConfiguration();
config.ConfigureFactory("myserver.com");
using (var context = new DirectoryContext(config))
{
    context.Log = Console.Out;

    var user = context.Query<User>()
        .Where(u => u.CommonName == "Andrew Fuller")
        .FirstOrDefault();    
    Console.WriteLine(user.WhenChanged);

    user.Title = "Just Promoted";

    User updated = context.Update(user);
    Console.WriteLine(updated.WhenChanged);
}

C# Dynamic Querying

var config = new LdapConfiguration();
config.ConfigureFactory("myserver.com");
using (var context = new DirectoryContext(config))
{
    context.Log = Console.Out;

    IDirectoryAttributes user = context
        .Query("CN=Users,CN=Employees,DC=Northwind,DC=local", objectClass: "User")
        .Where("givenname=Andrew")
        .Where(da => Filter.Equal(da, "sn", "Fuller"))
        .FirstOrDefault();
    Console.WriteLine(user.GetDateTime("WhenChanged"));

    user.Set("title", "Just Promoted");

    IDirectoryAttributes updated = context.Update(user);
    Console.WriteLine(user.GetDateTime("WhenChanged"));
}

C# Query By Example

var config = new LdapConfiguration();
config.ConfigureFactory("myserver.com");
using (var context = new DirectoryContext(config))
{
    context.Log = Console.Out;

    var example = new 
                  {
                       DistinguishedName = "",
                       Cn = "",
                       Title = "",
                       ObjectGuid = default(Guid),
                       ObjectSid = default(SecurityIdentifier),
                       WhenChanged = default(DateTime)
                  };

    var user = context
        .Query(example, "CN=Users,CN=Employees,DC=Northwind,DC=local", 
                  objectClass: "User")
        .Where(u => u.Cn == "Andrew Fuller")
        .FirstOrDefault();    
    Console.WriteLine(user.WhenChanged);

    var toUpdate = new DirectoryAttributes(user.DistinguishedName);
    toUpdate.Set("title", "Just Promoted");

    var updated = context.Update(toUpdate);
    Console.WriteLine(updated.WhenChanged);
}

VB Mapped Objects

<DirectorySchema("CN=Users,CN=Employees,DC=Northwind,DC=local")>
Public Class User
    Inherits DirectoryObjectBase

	<DistinguishedName()>
	Public Property DistinguishedName As String

	<DirectoryAttribute("cn", ReadOnly = true)>
	Public Property CommonName As String

	<DirectoryAttribute()>
	Public Property Title As String

    	<DirectoryAttribute(StoreGenerated:=True)>
    	Public Property ObjectGuid As Guid

    	<DirectoryAttribute(StoreGenerated:=True)>
    	Public Property SecurityIdentifier As SecurityIdentifier

   	<DirectoryAttribute(StoreGenerated:=True)>
    	Public Property WhenChanged As DateTime
End Class

Dim config As New LdapConfiguration()
config.ConfigureFactory("myserver.com")
Using context As New DirectoryContext(config)
	context.Log = Console.Out

	Dim user = context.Query(Of User)() _
		.Where(Function(u As User) u.CommonName.Equals("Andrew Fuller")) _
		.FirstOrDefault()
	Console.WriteLine(user.WhenChanged)

	user.Title = "Just Promoted"

	Dim updated = context.Update(user)
	Console.WriteLine(updated.WhenChanged)
End Using

VB Dynamic Querying

Dim config As New LdapConfiguration()
config.ConfigureFactory("myserver.com")
Using context As New DirectoryContext(config)
	context.Log = Console.Out

	Dim user = context.Query("CN=Users,CN=Employees,DC=Northwind,DC=local", objectClass:="User") _
		.Where("givenname=Andrew") _
                .Where(Function(da As IDirectoryAttributes) Filter.Equal(da, "sn", "Fuller")) _
		.FirstOrDefault()
	Console.WriteLine(user.GetDateTime("whenchanged"))

	user.Set("title", "Just Promoted")

	Dim updated = context.Update(user)
	Console.WriteLine(user.GetDateTime("whenchanged"))
End Using

VB Query By Example

Dim config As New LdapConfiguration()
config.ConfigureFactory("myserver.com")
Using context As New DirectoryContext(config)
	context.Log = Console.Out

	Dim example = New With
		  {
			   .DistinguishedName = "",
			   .Cn = "",
			   .Title = "",
			   .ObjectGuid = DirectCast(Nothing, Nullable(Of Guid)),
			   .ObjectSid = DirectCast(Nothing, SecurityIdentifier),
			   .WhenChanged = DirectCast(Nothing, Nullable(Of DateTime))
		  }

	Dim user = context.Query(example, "CN=Users,CN=Employees,DC=Northwind,DC=local", objectClass:="User") _
		.Where("cn=Andrew Fuller") _
		.FirstOrDefault()
	Console.WriteLine(user.WhenChanged)
        
        Dim toUpdate = New DirectoryAttributes(user.DistinguishedName)
        toUpdate.Set("title", "Just Promoted")

	Dim updated = context.Update(toUpdate)
	Console.WriteLine(updated.WhenChanged)
End Using

Tested Servers

  • Microsoft Lightweight Directory Services
  • Microsoft Active Directory (Read Only Testing)
  • IBM Tivoli Directory (Read Only Testing)
  • Siemens DirX (Read Only Testing)
  • Apache Directory (Read Only Testing)

Disclaimer

This project is provided as is. I have tested the project primarily using Lightweight Directory Services, but each server will have different features and capabilities. I recommend thorough testing before using this project in a production environment.

Visit my blog: http://hattercoding.blogspot.com/.

Last edited Jul 23, 2012 at 4:41 AM by MadHatter22, version 26