Wednesday, 14 January 2009

LINQ Best Practice 1 – The Repository Pattern

I’ve been using LINQ a lot with my new project, in particular with the Entity Framework.  I have learned a lot about good practices with LINQ and I figured it would be a good idea to post them up here.  Contained in these posts are all those things I’ve learned and suggest could be useful to you.  They are best practices that work for me, if they work for you then great, but everyone’s solution is different.

Use the Repository Pattern

I can’t stress this enough, if you’re going to use LINQ to Entities then you will benefit enormously from the repository pattern, in particular if Unit Testing and / or TDD is important to you.  The repository pattern defines that you create an interface to your data source within a context and only use this interface for retrieving the data.  Your unit tests for controllers or business logic can then mock the interface into the data to provide logical feedback for the tests.

Here is an example repository for the Item table within my database.  I have a table called Item and I define standard methods for my repositories to implement, Get, Save, Search etc.

This is the interface:

public interface IItemRepository
{
    Item Get(int itemCodeID);
    List<ValidationErrorResult> Save(Item item);
    void Delete(Item item);
    List<ValidationErrorResult> Add(Item item);
    List<Item> Search(string name, string description, int pageNumber, int itemsPerPage);
}

I like to return lists, some people may wish to return IQueryable.  If you return an IQueryable then you’re accepting that the data may not be physically fetched from the database when within the repository source.  In our project I believe it is better to be in control of when we get the data, but this is not for everyone.  There is a great article about returning List over IQueryable or not here.

And my implementation:

public class ItemRepository : IItemRepository
{
    private IQueryable<Item> _DataSource;
    private LynxEntities _Entities;
 
    public ItemRepository(LynxEntities entities)
    {
        _Entities = entities;
        _DataSource = _Entities.Item;
    }
 
    public ItemRepository(IQueryable<Item> dataSource)
    {
        _DataSource = dataSource;
    }
 
    Item IItemRepository.Get(int itemCodeID)
    {
        // implementation
    }
 
    List<ValidationErrorResult> IItemRepository.Save(Item item)
    {
        // implementation
    }
 
    void IItemRepository.Delete(Item item)
    {
        // implementation
    }
 
    List<ValidationErrorResult> IItemRepository.Add(Item item)
    {
        // implementation
    }
 
    List<Item> IItemRepository.Search(string name, string description, int itemsPerPage, int pageNumber)
    {
        // implementation
    }
}

I’ve removed all the implementation because it’s not relevant.  The important part is the constructors.  The first constructor is the default constructor.  It is very important with LINQ to Entities that you pass the entity object into the constructor instead of creating it.  This is because if you don’t and you get items from another repository with a different entity object then your relationships are not going to work.

The second constructor allows me to construct a list of objects with which to test in my unit testing environment.  We use MSTest and Rhino Mocks to support our testing framework.  Each of my repository classes will have a test class associated with it, and each test class will have a method to setup the data to test with.

List<Item> data = new List<Item>
{
    new Item
    {
        // Item details
    },
    new Item
    {
        // Item details
    }
};
 
ItemRepository target = new ItemRepository(data);

Allowing me to easily test my database functions without having to connect to any form of real data source.  You will run into problems when you try to run the SaveChanges methods of the entity model as when unit testing your entities object will be null.  You can just ensure that you test for null before saving changes to the data model like this:

if (_Entities != null)
{
    _Entities.SaveChanges();
}

Implementing the Repository Pattern

Once we have the repository we need to implement it.  Code examples are the best way to show this so I’ll do that.  We’re using ASP.NET MVC so our controllers define the instance of the repository.  As the controller is the master of the unit of work, we create the entity model in the controller and give it to the repositories that we create instances of.

// Constructor
public ItemController()
{
    LynxEntities entities = new LynxEntities();
    _ItemRepository = new ItemRepository(entities);
    _AnotherRepository = new AnotherRepository(entities);
 
}

Because we are using the same entity model in all the repositories in our unit of work I can load an object from my “AnotherRepository” and set it against an item pulled from my “ItemRepository” if I need to.  If they did not share the same entity model you would get an error when you tried to save changes.

In my test classes for my controllers we use Rhino Mocks to mock the interface to the repository.  Each of my test classes defines a SetupMocks method that will setup the mocks for each interface I am mocking.

private void SetupMocks(MockRepository mocks, IItemRepository items)
{
    using (mocks.Record())
    {
        // Setup the item repository
        SetupResult
            .For(items.Get(""))
            .Return(null).Repeat.AtLeastOnce();
        SetupResult
            .For(items.Get("itemA"))
            .Return(new Item
            {
                // Item Details
            }).Repeat.AtLeastOnce();
    }
}

Now I can unit test my controller just as if it were connected to the database.

The Repository Pattern is a very straight forward solution that gives you the advantages of testable code, reusable code modules and separation of concerns between the database business rules and the application business rules.  Hopefully you find it useful.

3 comments:

ch1c0 s4b10 said...

What other uses beside making the code more testable and the ability to delay or work separatly the database, does creating the interface has?

Odd said...

The main goal is to make the code more testable, however it also allows you to be more flexible with your implementation while keeping the usage of the repository standard. There are arguments for and against using interfaces, if you are against them it would be more than feasable to implement the repository pattern without the interface. Unit testing would be very difficult without them though.

best practice said...

Before you install any software in your unit, make sire that you have it check my someone knowledgeable to avoid hassle.