HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpModerate

Following Repository Pattern properly

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
patternfollowingproperlyrepository

Problem

I am new to learning Repository Pattern. I am developing a site in MVC 4 (I'm new to it as well).

The way I am using Repository pattern as follows:

-
I created IRepository interface as follows:

public interface IRepository    
{        
    void Insert(T entity);
    void Delete(T entity);
    IQueryable SearchFor(Expression> predicate);
    IQueryable GetAll();
    T GetById(int id);
}


-
Then I created a base class which implements the above interface as follows:

public class BaseRepository : IRepository where TEntity : class
{
    private readonly DbContext _dbContext;

    public BaseRepository(DbContext dbContext)
    {
        _dbContext = dbContext;
    }

    public void Insert(TEntity entity)
    {
        _dbContext.Set().Add(entity);
        _dbContext.SaveChanges();
    }

    public void Delete(TEntity entity)
    {
        _dbContext.Set().Remove(entity);
        _dbContext.SaveChanges();
    }

    public IQueryable SearchFor(Expression> predicate)
    {
        return _dbContext.Set().Where(predicate);
    }

    public IQueryable GetAll()
    {
        return _dbContext.Set();
    }

    public TEntity GetById(int id)
    {
        return _dbContext.Set().Find(id);
    }
}


-
Now for each repository I want to create, I create another interface which contains methods specific to that class. E.g if I want to create a CustomersRepository, I create an interface ICustomersRepository as follows:

public interface ICustomersRepository: IRepository
{
    IEnumerable GetRecentCustomers();
    Customer GetByName(string customerName);
}


-
Now I create CustomersRepository class, derive it from BaseRepository and implement ICustomersRepository. as follows:

```
public class CustomersRepository : BaseRepository, ICustomersRepository
{
private readonly DbContext _dbContext;

public CustomersRepository(DbContext dbContext) : base(dbContext)
{
_dbContext = dbContext;
}

public IEnumerable GetR

Solution

-
You can make DbContext protected property in your base implementation, so you don't have to declare it in every single derived class.

-
You might want to consider extracting Insert and Delete methods to separate interface, because often you want to make some of your repositories readonly.

Implementation may look like that:

interface IRepository    
{        
    IQueryable SearchFor(Expression> predicate);
    IQueryable GetAll();
    T GetById(int id);
}

interface IEditableRepository : IRepository
{
    void Insert(T entity);
    void Delete(T entity);
}

class ReadOnlyRepositoryBase : IRepository
{...}

class EditableRepositoryBase : ReadOnlyRepositoryBase, IEditableRepository
{...}


this way you can distinct readonly repositories from non-readonly at compilation time.

-
Passing dbContext to every repository is not normally an issue, because usually in addition to your repositories, you also implement factory object, which creates your repositories for you, so you don't have to call constructor explicitly. This factory can be made a singleton, so you can access it at any point in your code. Alternatively, you can register your repositories in some container, or you can use both approaches.
If you are familiar with inversion of control and dependency injection (because there is definitely a learning curve), your best bet is to use a container.

Here is an example (using Castle Windsor):

public class RepositoryFactory : IDisposable
{
    private IWindsorContainer _container;

    public void Open()
    {
        _container = new WindsorContainer();

        //register dependencies
        _container.Register(Component.For().ImplementedBy());

        //register repositories
        _container.Register(Component.For().ImplementedBy());
    }

    public TRepository GetRepository() where TRepository : class
    {
        return _container.Resolve();
    }

    public Dispose()
    {
        if (_container == null) return;
        _container.Dispose();
        _container = null;
    }

    public void Close()
    {
        Dispose();
    }
}


Then you can use it like this:

var f = new RepositoryFactory();
f.Open();
var rep = f.GetRepository();
f.Close();


Alternatively, you can implement your own container using reflection to instantiate your repositories, or you can use a dictionary. Or w/e, really. This implementation is obviously no singleton, but nothing stops you making one, if you feel like it.

Apart from that, your implementation looks fine to me. I didn't quite get your first issue though.

Code Snippets

interface IRepository<T>    
{        
    IQueryable<T> SearchFor(Expression<Func<T, bool>> predicate);
    IQueryable<T> GetAll();
    T GetById(int id);
}

interface IEditableRepository<T> : IRepository<T>
{
    void Insert(T entity);
    void Delete(T entity);
}

class ReadOnlyRepositoryBase<T> : IRepository<T>
{...}

class EditableRepositoryBase<T> : ReadOnlyRepositoryBase<T>, IEditableRepository<T>
{...}
public class RepositoryFactory : IDisposable
{
    private IWindsorContainer _container;

    public void Open()
    {
        _container = new WindsorContainer();

        //register dependencies
        _container.Register(Component.For<DbContext>().ImplementedBy<DbContext>());

        //register repositories
        _container.Register(Component.For<ICustomersRepository>().ImplementedBy<CustomersRepository>());
    }

    public TRepository GetRepository<TRepository>() where TRepository : class
    {
        return _container.Resolve<TRepository>();
    }

    public Dispose()
    {
        if (_container == null) return;
        _container.Dispose();
        _container = null;
    }

    public void Close()
    {
        Dispose();
    }
}
var f = new RepositoryFactory();
f.Open();
var rep = f.GetRepository<ICustomersRepository>();
f.Close();

Context

StackExchange Code Review Q#27598, answer score: 14

Revisions (0)

No revisions yet.