When using Entity Framework you run into the problem of having either one repository object for each database or having to not use an Inversion of Control due to having to new the Entities Context each time. I have found that this hit on the architecture side is not required.
This is a follow up to the POCO and Context separation post here. It uses that separation to avoid circular references.
Lets start with our Generic Repository and Interface.
public class EntityFrameworkRepository : IRepository
{
private ObjectContext _entities;
public EntityFrameworkRepository(ObjectContext context)
{
_entities = context;
}
public IQueryable<T> FindAll<T>() where T : class
{
return _entities.CreateObjectSet<T>();
}
public IQueryable<T> Find<T>(Expression<Func<T, bool>> where) where T : class
{
return _entities.CreateObjectSet<T>().Where(where);
}
public T Single<T>(Expression<Func<T, bool>> where) where T : class
{
return _entities.CreateObjectSet<T>().Where(where).Single();
}
public T SingleOrDefault<T>(Expression<Func<T, bool>> where) where T : class
{
return _entities.CreateObjectSet<T>().Where(where).SingleOrDefault();
}
public T First<T>(Expression<Func<T, bool>> where) where T : class
{
return _entities.CreateObjectSet<T>().Where(where).First();
}
public T FirstOrDefault<T>(Expression<Func<T, bool>> where) where T : class
{
return _entities.CreateObjectSet<T>().Where(where).FirstOrDefault();
}
public T Add<T>(T entity) where T : class
{
_entities.CreateObjectSet<T>().AddObject(entity);
_entities.SaveChanges();
return entity;
}
public void Delete<T>(T entity) where T : class
{
_entities.DeleteObject(entity);
_entities.SaveChanges();
}
public T Attach<T>(T entity) where T : class
{
_entities.AttachTo(entity.GetType().ToString(),entity);
_entities.SaveChanges();
return entity;
}
public int SaveChanges()
{
return _entities.SaveChanges();
}
}
public interface IRepository
{
IQueryable<T> FindAll<T>() where T : class;
IQueryable<T> Find<T>(Expression<Func<T,bool>> where) where T : class;
T Single<T>(Expression<Func<T, bool>> where) where T : class;
T SingleOrDefault<T>(Expression<Func<T, bool>> where) where T : class;
T First<T>(Expression<Func<T, bool>> where) where T : class;
T FirstOrDefault<T>(Expression<Func<T, bool>> where) where T : class;
T Add<T>(T entity) where T : class;
void Delete<T>(T entity) where T : class;
T Attach<T>(T entity) where T : class;
int SaveChanges();
}
Notice that we pass in the Object Context. This is what enables us to separate the usage from the declaration. I am going to use Structure Map as it is my preferred IoC but most IoCs implement this functionality.

This is in the configuration code block for Structure Map. Notice that the ObjectContext is created to a named instance of the IRepository. The application services are created with the database that they hit. This allows you two things.
1. Re-use of the interfaces and repository objects between databases.
2. Changing the database for a service is now just an IoC Configuration Change.
Enjoy.
436a3671-f189-414e-94df-9c94b0bec7a1|1|5.0
Design Patterns, Entity Framework