I’ve recently been working with LINQ-to-SQL as the ORM for a project. Although not my preferred choice I’ve been looking at the best ways I can apply the technology within the bounds of the project. In this case this means applying the Repository pattern.

In this context the primary need for the repository was to break the direct link between the LINQ-to-SQL context and the business logic so that the business logic could be relatively independent of the database and could be tested in isolation. The business logic does tend to have queries in it which could be separated into query objects, but for this project that was unfortunately a stretch too far. Even so the repository has given us significant value.

In implementing this pattern I started with something that looks very much like this example from Code Project, but with the use of expressions as suggested in the comments for performance reasons. The actual implementation varied somewhat to match other infrastructure components that are not relevant here.

This worked well but I have been finding that LINQ-to-SQL requires more explicit database interactions than other alternatives such as NHibernate. This means that I’m injecting rather more repositories into business logic classes than I’d like. Even with relatively fine grained service classes that adhere relatively well to the Single Responsibility Principal the number of repositories is a concern.

My solution has been to change the repository interface (actually to create a new variant to avoid having to modify large amounts of existing code unnecessarily). This repository interface is not generic but has generic methods. It looks something like this:

public interface IRepository
{
    TEntity Single<TEntity>(Expression<Func<TEntity, bool>> query)
        where TEntity : class;

    IQueryable<TEntity> FindQueryable<TEntity>()
        where TEntity : class;

    void Add<TEntity>(TEntity instance)
        where TEntity : class;

    void DeleteAll<TEntity>(IEnumerable<TEntity> instances)
        where TEntity : class;
}

As the repository methods treat all entities equivalently there is no need to have a distinct instance for each entity type. FxCop will complain about some of the methods but it’s wrong in this case, the generic parameters are in context a simplification.

This approach works reasonably well for LINQ-to-SQL but I wouldn’t suggest it on other contexts. With NHibernate based systems which allow for proper DDD I’d suggest query objects that encapsulate the queries and work directly with the NHibernate abstractions are preferable. But that’s another post entirely.