Software Twist – Adrian Tosca Blog

Implementing a Simple Generic Repository with LinqToSql

Posted in Software Development by Adrian Tosca on 2009, April 17

The Repository pattern

The Repository is a design pattern often used in Domain Driven Design (DDD) to help the domain layer access data needed from the underlying persistence layer.

The Repository pattern was described by Martin Fowler as:

A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. Client objects construct query specifications decoratively and submit them to Repository for satisfaction. Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes. Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer.

In DDD the repository is tightly linked with the aggregate notion. The aggregate is a hierarchy of objects that are treated as a unit for the purpose of data changes. The aggregate components are accessed only from its root object. A repository is usually build around an aggregate.

As an example we may have a Car aggregate that has a collection of Wheels.

Car and Wheels Model

In our domain we will never refer to a wheel directly but first get a car and have access to its wheels.

Get Car Aggregate from Repository

Most of the time we need just a couple of operations to deal with aggregates on the repository.  With the above example we would have to implement in the repository methods to:

  • Add a new Car
  • Remove a Car
  • Get the Car by Id
  • Get a filtered list of Cars

Implementing this in LinqToSql is pretty straightforward but it has its catches.

Add and Remove

The simplest to implement are the add and remove methods:

    public class Repository<T> where T : class {
        CarsDataContext _dataContext = new CarsDataContext();
        public void Add(T entity) {
            DataContext.GetTable<T>().InsertOnSubmit(entity);
            DataContext.SubmitChanges();
        }
        public void Remove(T entity) {
            DataContext.GetTable<T>().DeleteOnSubmit(entity);
            DataContext.SubmitChanges();
        }
    }

Nothing special here. The generic GetTable of the LinqToSQL data context is used to insert/delete the entity and then SubmitChanges is called to send the changes to the database. The methods can be used like this:

    Repository<Car> carRepository = new Repository<Car>();

    // create a new car and add it
    Car newCar = new Car();
    carRepository.Add(newCar);

    // get an existingCar, then remove it
    Car existingCar = ...
    carRepository.Remove(existingCar);

Get By Id

Implementing the get by id method is a little more challenging. The first thing is to ensure that the model has the ‘Id’ notion. By default the LinqToSql classes do not have a direct way of exposing an identifier meta-data. We can have this by adding an interface and ensure the classes implements it:

    public interface IIdentifiable {
        int Id { get; }
    }
    public partial class Car : IIdentifiable {
    }

All the classes that need to be get by Id will have to implement the IIdentifiable interface. This is done in the code above by adding a partial class that implements the IIdentifiable interface. There is a catch here. If a consistent naming convention is used and all the classes have an ‘Id’ property then the above code is all we need.

With the classes prepared we can then write:

    public class Repository<T> where T : class, IIdentifiable {
        public T GetById(int id) {
            T entity = DataContext.GetTable<T>().SingleOrDefault(e => e.Id.Equals(id));
            return entity;
        }
    }

Please note the e.Id.Equals(id) above. LinqToSql does not know how to generate the == operator when interfaces are involved but it knows to generate the proper expression tree with Equals.

The GetById method can then be used like:

    Repository<Car> carRepository = new Repository<Car>();
    Car existingCar = carRepository.GetById(1);

The generated SQL contains what we expect, a parametrized query:

    exec sp_executesql N'SELECT [t0].[Id], [t0].[Make], [t0].[Year]
    FROM [dbo].[Car] AS [t0]
    WHERE [t0].[Id] = @p0',N'@p0 int',@p0=1

Getting Aggregate Elements

As LinqToSql supports lazy loading so all is needed is to access the elements from the root.

    Car car = carRepository.GetById(1);
    Console.WriteLine(car.Make);
    Console.WriteLine(car.Wheels.Count); // additional query will hit the database

Clean and easy. For more complex scenarios where one would need to control the loading behavior the DataLoadOptions of the LinqToSql can be used.

Get a Filtered List

The simplest to implement this is to allow expression filters as parameters:

    public IQueryable<T> GetByFilter(Expression<Func<T, bool>> filter) {
        return DataContext.GetTable<T>().Where(filter);
    }
    // and this can be used like:
    IQueryable<Car> cars = carRepository.GetByFilter(e => e.Year == 2009 && e.Make == "Ford");

An IQueryable is returned to allow simple UI integration. For example using a GridView with a LinqToSql source will automatically have sorting and paging implemented with this approach. The downside of this approach is that the DataContext will remain open up to the UI layer and this might introduce performance penalties. The alternative would be to return an IEnumerable instead and let the UI handle the pagination and sorting.

Conclusion

The solution presented is not without flaws. The biggest one is the tight link between the DB implementation and the model, forced by the LinqToSql architecture. There is also the inconvenient of having all primary keys named ‘Id’ and having to write partial classes for implementing the IIdentifiable interface. But there are also a couple of nice things like a very simple and clean usage, the possibility to use generics with aggregates and, maybe the best one, the possibility of avoiding boiler plate code.

Download the supporting code for this article (12.0 KB).

Advertisements

New Version of jQuery Dropdown Checkbox List Plugin

Posted in Software Development by Adrian Tosca on 2009, April 11

One of the users of the dropdown-check-list plugin added a patch containing an update to take into consideration the optgroup tags, part of the select HTML element. After playing around with it and adding a few modifications, I uploaded a new version to the codebase that has this feature:

Groups in dropdown-check-list plugin

Groups in dropdown-check-list plugin

The above image corresponds to the following html code:


    <select id="s6" multiple="multiple">
        <optgroup label="Letters">
            <option>A</option>
            <option>B</option>
            <option selected="selected">C</option>
        </optgroup>
        <optgroup label="Numbers">
            <option>1</option>
            <option>2</option>
            <option selected="selected">3</option>
        </optgroup>
    </select>

The optgroup tags of the HTML select element marked with multiple attribute are inserted in the drop down container with their own css class ui-dropdownchecklist-group. The options that are part of an optgroup get a ui-dropdownchecklist-indent css class for custom indentation.

The new version can be downloaded from the google code project.

Hope to find this new feature usefull.

Tagged with: ,

It Takes All the Running You Can Do, to Keep in the Same Place

Posted in Miscellaneous by Adrian Tosca on 2009, April 2

Leigh Van Valen proposed the Red Queen evolutionary hypothesis  that introduced the idea that there is a constant ‘arms race’ between co-evolving species. The term is taken from the  Lewis Carroll’s Through the Looking-Glass where Red Queen tells Alice:

it takes all the running you can do, to keep in the same place. If you want to get somewhere else, you must run at least twice as fast as that.

Van Valen found that improvement in one species will lead to improvement in the co-evolving species because when a species develops a special ability (for example foxes running faster) it’s co-evolving species will also  improve its ability (for example, rabbits running faster).

John Tenniel's classic illustration of Alice and the Red Queen running

OK, so what all that has to do with software development? It just occurred to me that there are a couple of parallels we can draw with that:

Competitive frameworks are improving side by side.

If a framework stops to evolve it is likely a target for extinction. It is a very visible phenomenon these days that if a framework improve a certain aspect it is borrowed by other frameworks. The same is true with programming languages.

Software developers are continously improving their skills

There are always new things to learn and if you stop, you will drift away. If one does not learn, the others will and he’s knowledge will sun be obsolete. You must lean every day just to stay in the same place!

Comments Off on It Takes All the Running You Can Do, to Keep in the Same Place