Sergey Shishkin

on agile software development

Specification Pattern Revised

(see also repository and unit of work)

Unfortunately, current implementation of Linq2NH does not support queries like this:


from
customer in repository.AllEntities()

where specification.IsSatisfiedBy(customer)

select customer

The cause is that Linq2NH can’t translate the call to the specification’s method into the appropriate call to the Criteria API. What can be done instead is encapsulation of queries into C# extension methods. We can do this in two ways:

Chaining IQueryable<T>

First one is chaining of IQueryable<T> methods like this:


public
static IQueryable<Customer> FindByName(this IQueryable<Customer> customers, string query)

{

    return

        from customer in customers

        where customer.FirstName.StartsWith(query) ||

            customer.LastName.StartsWith(query)

        select customer;

}


from
customer in repository.AllEntities().FindByName(name)

select customer;

Extending IRepository<T>

Alternatively, you can write extension methods for IRepository<Customer> like this:


public
static Collection<Customer> FindByName(this IRepository<Customer> repository, string query)

{

    var linq =

        from customer in repository.AllEntities()

        where customer.FirstName.StartsWith(query) ||

            customer.LastName.StartsWith(query)

        select customer;

    return new Collection<Customer>(linq.ToList());

}


var
customers = customerRepository.FindByName(name);

These two approaches are not a mutual exclusion. You can apply them together for better results. Encapsulate simple queries into IQueryable<T> extension methods. Then combine them to implement more complex IRepository<T> extension methods, available to the application layer.

 

Advertisements

Written by Sergey Shishkin

17.08.2008 at 16:32

Posted in Data Access

%d bloggers like this: