How to use a custom DbContext to implement a Repository in Entity Framework?

c# dbcontext entity-framework repository

Question

We are starting to develop a small framework in our company, to share code between different applications. For data access we are using EF4. We have a custom DbContext class and a generic Repository:

public class RMDbContext : DbContext
{
    // ....
}

public interface IRepository 
{
    IQueryable<T> All();
    void Delete(T entity) where T : class;
    void Add(T entity) where T : class;
    void Update(T entity) where T : class;
    int SaveChanges();
    void RollbackChanges();
}

The problem here is how to implement the repository, using our custom DbContext class (RMDbContext). My co-worker thinks that the best way is to let RMDbContext implement the IRepository interface:

public class RMDbContext : DbContext, IRepository
{
    // ....
}

To be honest I don't like this approach, because the context is tied to a specific contract (IRepository). IMO it's better to create a repository implementation that uses the RMDbContext, something like this:

public class Repository<T> : IRepository where T : RMDbContext, new()
{
    protected readonly RMDbContext context;

    public class Repository()
    {
         context = new T();
    }

    // ....
}

What do you think about these 2 approaches? Which one would you choose, and why?

1
1
3/1/2013 8:30:47 PM

Accepted Answer

What we did at work was to implement a pattern like this:

interface ICRUD<T> : ICreatable<T>, IRetrievable<T>, IUpdatable<T>, IDeletable<T>
{
}

interface ICreatable<T>
{
    T Create();
}

interface IRetrieve<T>
{
    T Retrieve(params object[] keys);
}

interface IUpdatable<T>
{
    void Update(T existing);
}

interface ICreatable<T>
{
    void Delete(T existing);
}

And then we created an Entity-powered base repository:

public abstract class BaseRepository<TModel, TEntities> where TEntities : IDbSet<TModel>
{
    protected TEntities Entities {get; set;}
    protected DbContext Db {get; set;}

    public BaseRepository (DbContext db, TEntities entities)
    {
        Db = db;
        Entities = entities;
    }

    public virtual TModel Create() { return Entities.Create (); }
    public virtual TModel Retrieve (params object[] keys) { return Entities.Find (keys); }
    public virtual void Update (TModel existing) { Db.Entry(existing).State = Modified; }
    public virtual void Delete (TModel existing) { Db.Entry(existing).State = Removed; }
}

If you notice, the BaseRepository doesn't actually use ICRUD, just has identical method signatures. Since we code to interfaces, this lets us use a lot of shared code without exposing functionality we don't want with the base classes. A developer is free to implement the data store however they wish (ICRUD can talk to a webservice, for instance) with no knowledge of Entity, or they're also free to augment behavior provided by the BaseRepository by overriding any of the provided methods and doing something differently.

3
11/15/2011 12:54:31 AM

Popular Answer

personally i would encourage you guys to not create anything, just use the dbContext, it has all the methods you need anyways.

I myself implemented #1 (implementing IRepository), but you would end up doing some funky programming to get to the correct ObjectSet or EntitySet to add or delete from your Add/Delete methods.

That code would keep becoming more complex as you add inheritance hierarchies in your objectmodel.



Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow