Implementation of a Generic Repository Beauty, with Ninject the Beast
Posted: May 29, 2011 Filed under: C#, Code, Entity Framework | Tags: Control, Design, First, Generic, Inversion, Ninject, Pattern, Repository 5 Comments »I really should be studying. But why study when I can blog right? Well, I have been meaning to write this post for a while now, and here it is.
The Repository Pattern is invaluable when working with the data, particularly in MVC. It encapsulates a lot of redundant and hopefully generic operations, I use it to encapsulate operations on the Entity Framework Code First ORM. My implementation doesn’t use Unit of Work which tracks changes and updates the database accordingly. Instead, I let myself decide. It’s not that bad.
The Context
Firstly, there is the context interface. It can expose methods, but I didn’t need to. Let’s imagine this context is for a shop.
This interface is important because it’ll be used by Ninject to wire everything up.
public interface IShopContext
{
}
The concrete implementation of the context might look like this.
public class CareContext: DbContext, IShopContext
{
public DbSet<Fruit> Fruits { get; set; }
public ShopContext()
{
}
}
The Entities
Fruit above is an entity and there can be many more. The entities derive from an abstract Identity class. What it is, is pretty obvious.
public abstract class Identity
{
public Guid ID { get; set; }
}
Now let’s look at the example Fruit.
public class Fruit: Identity
{
public string Name { get; set; }
public int AmountInShop { get; set; }
}
The Repository
public interface IRepository<TEntity> where TEntity : Identity
{
TEntity Add(TEntity model, bool persist = false);
TEntity Get(Guid id);
IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> predicate);
IEnumerable<TEntity> GetAll();
TEntity Update(TEntity model, bool persist = false);
void Remove(Guid id, bool persist = false);
void Remove(TEntity model, bool persist = false);
void Save();
}
So these are some of the operations that the repository will perform. As you can see, I take care of the persistence using the optional parameter persist.
And now… the concrete implementation of the repository.
public class Repository<TEntity> : IRepository<TEntity> where TEntity : Identity
{
private DbContext Context;
private DbSet<TEntity> DBSet;
public Repository(IShopContext context)
{
Context = context as DbContext;
DBSet = Context.Set<TEntity>();
}
public TEntity Get(Guid id)
{
TEntity model = DBSet.Find(id);
return model;
}
public IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> predicate)
{
return DBSet.Where(predicate).AsEnumerable();
}
public IEnumerable<TEntity> GetAll()
{
return DBSet.AsEnumerable<TEntity>();
}
public TEntity Add(TEntity model, bool persist = false)
{
model.ID = Guid.NewGuid();
DBSet.Add(model);
Save(persist);
return model;
}
public TEntity Update(TEntity model, bool persist = false)
{
Context.Entry(model).State = EntityState.Modified;
Save(persist);
return model;
}
public void Remove(Guid id, bool persist = false)
{
TEntity model = DBSet.Find(id);
Remove(model, persist);
}
public void Remove(TEntity model, bool persist = false)
{
if (model != null)
{
Context.Entry<TEntity>(model).State = EntityState.Deleted;
Save(persist);
}
}
public void Save()
{
Save(true);
}
private void Save(bool persist)
{
if (persist)
{
Context.SaveChanges();
}
}
}
There you have it. It’s very simple to read really. It just spells out the methods defined in the interface and also provides logic for persistence when you want it.
The Ninject
Now all of this is pretty useless without Ninject. You’ll have noticed I used Inversion of Control while implementing the repository. Ninject is available on Nuget.
While registering the services on Ninject, I can tell it to provide a ShopContext when a IShopContext is required. The repository is bound to an interface, this context can be a development or deployment context, depending. Also, since I want to use the same context always, I bind it using ToConstant.
As for when a repository operating on a certain entity is requested, Ninject finds its type and provides accordingly.
private static void RegisterServices(IKernel kernel)
{
IShopContext shopContext = new ShopContext();
kernel.Bind(typeof(IShopContext)).ToConstant(shopContext);
kernel.Bind(typeof(IRepository<>)).To(typeof(Repository<>));
}
Hope that wasn’t too long a post, it probably is my longest so far. Till next time, then.

With a constant instance of ShopContext, don’t you think that you might run into a situation where there are two requests executing at the same time, both with pending changes, where one finishes before the other and calls Save(true) before the other request is done (which means that the longer request would have some of it’s changes be part of one transaction and the remainder of it’s changes in another transaction)?
Yes definitely, data access layers always have concurrency problems and can be resolved by some of the suggestions here. I am looking to improve my implementation, possibly with an optimistic concurrency check.
this is interesting , thank you.
It’s not clear to me: where should I call RegisterServices method in MVC application?
One time for each controller? Or just ones? But where?
I’ve seen the call made in in Global.asax (depending on the case, called once). I guess that’s a simple way of doing it. I personally use a WebActivator for Ninject.