Alex Rivera | Logout

Trying to simplify our repository pattern

Asked 2012-08-23T17:24:36.823
13

Currently we have implemented a repository pattern at work. All our repositories sit behind their own interfaces and are mapped via Ninject. Our project is quite large and there are a couple quirks with this pattern I'm trying to solve.

First, there are some controllers where we need upwards of 10 to 15 repositories all in the same controller. The constructor gets rather ugly when asking for so many repositories. The second quirk reveals itself after you call methods on multiple repositories. After doing work with multiple repositories we need to call the SaveChanges method, but which repository should we call it on? Every repository has one. All repositories have the same instance of the Entity Framework data context injected so picking any random repository to call save on will work. It just seems so messy.

I looked up the "Unit Of Work" pattern and came up with a solution that I think solves both problems, but I'm not 100% confident in this solution. I created a class called DataBucket.

// Slimmed down for readability
public class DataBucket
{
    private DataContext _dataContext;

    public IReportsRepository ReportRepository { get; set; }
    public IEmployeeRepository EmployeeRepository { get; set; }
    public IDashboardRepository DashboardRepository { get; set; }

    public DataBucket(DataContext dataContext,
        IReportsRepository reportsRepository,
        IEmployeeRepository employeeRepository,
        IDashboardRepository dashboardRepository)
    {
        _dataContext = dataContext;
        this.ReportRepository = reportsRepository;
        this.EmployeeRepository = employeeRepository;
        this.DashboardRepository = dashboardRepository;
    }

    public void SaveChanges()
    {
        _dataContext.SaveChanges();
    }
}

This appears to solve both issues. There is now only one SaveChanges method on the data bucket itself and you only inject one object, the data buc

Edit
Report

1 Answer

6

First, there are some controllers where we need upwards of 10 to 15 repositories all in the same controller.

Say hello to Abstract factory pattern. Instead of registering all repositories in Ninject and injecting them to controllers register just single implementation of the factory which will be able to provide any repository you need - you can even create them lazily only if the controller really needs them. Than inject the factory to controller.

Yes it also has some disadvantages - you are giving controller permission to get any repository. Is it problem for you? You can always create multiple factories for some sub systems if you need or simply expose multiple factory interfaces on single implementation. It still doesn't cover all cases but it is better than passing 15 parameters to constructor. Btw. are you sure those controllers should not be split?

Note: This is not Service provider anti-pattern.

After doing work with multiple repositories we need to call the SaveChanges method, but which repository should we call it on?

Say hello to Unit of Work pattern. Unit of Work is logical transaction in your application. It persists all changes from logical transaction together. Repository should not be responsible for persisting changes - the unit of work should be. Somebody mentioned that DbContext is implementation of Repository pattern. It is not. It is implementation of Unit of Work pattern and DbSet is implementation of Repository pattern.

What you need is central class holding the instance of the context. The context will be also passed to repositories because they need it to retrieve data but only the central class (unit of work) will offer saving changes. It can also handle database transaction if you for

answered 2012-08-23T19:43:46.653

Your Answer