Generic Repository for Entity Framework with DbContext and Code First

I’ve recently been developing a small n-tier application using Domain Driven Development. In the interests of having a separation of concerns I built a generic repository that can be passed into my services.

 
using System;
using System.Data;
using System.Linq;
using System.Data.Entity;
using System.Linq.Expressions;
 
namespace Swink.Repositories
{
    public class Repository<TEntity, TContext> : IRepository<TEntity>, IDisposable 
        where TEntity : class
        where TContext : DbContext
    {
        protected TContext Context;
 
        public Repository(DbContext dbContext)
        {
            Context = dbContext as TContext;
        }
 
        public virtual TEntity Create()
        {
            return Context.Set<TEntity>().Create();
        }
 
        public virtual TEntity Create(TEntity entity)
        {
            return Context.Set<TEntity>().Add(entity);
        }
 
        public virtual TEntity Update(TEntity entity)
        {
            Context.Entry(entity).State = EntityState.Modified;
            return entity;
        }
 
        public virtual void Delete(long id)
        {
            var item = Context.Set<TEntity>().Find(id);
            Context.Set<TEntity>().Remove(item);
        }
 
        public virtual void Delete(TEntity entity)
        {
            Context.Set<TEntity>().Remove(entity);
        }
 
        public virtual void Delete(Expression<Func<TEntity, bool>> where)
        {
            var objects = Context.Set<TEntity>().Where(where).AsEnumerable();
            foreach (var item in objects)
            {
                Context.Set<TEntity>().Remove(item);
            }
        } 
 
        public virtual TEntity FindById(long id)
        {
            return Context.Set<TEntity>().Find(id);
        }
 
        public virtual TEntity FindOne(Expression<Func<TEntity, bool>> where = null)
        {
            return FindAll(where).FirstOrDefault();
        }
 
        public IQueryable<T> Set<T>() where T:class 
        {
            return Context.Set<T>();
        }
 
        public virtual IQueryable<TEntity> FindAll(Expression<Func<TEntity, bool>> where = null)
        {
            return null != where ? Context.Set<TEntity>().Where(where) : Context.Set<TEntity>();
        }
 
        public virtual bool SaveChanges()
        {
            return 0 < Context.SaveChanges();
        }
 
        /// <summary>
        /// Releases all resources used by the Entities
        /// </summary>
        public void Dispose()
        {
            if (null != Context)
            {
                Context.Dispose();
            }
        }
    }
}

The repo uses the following interface

using System;
using System.Linq;
using System.Linq.Expressions;
 
namespace Swink.Repositories
{
    public interface IRepository<TEntity>
    {
        /// <summary>
        /// Creates a new empty entity.
        /// </summary>
        TEntity Create();
 
        /// <summary>
        /// Creates the existing entity.
        /// </summary>
        TEntity Create(TEntity entity);
 
        /// <summary>
        /// Updates the existing entity.
        /// </summary>
        TEntity Update(TEntity entity);
 
        /// <summary>
        /// Delete an entity using its primary key.
        /// </summary>
        void Delete(long id);
 
        /// <summary>
        /// Delete the given entity.
        /// </summary>
        void Delete(TEntity entity);
 
        /// <summary>
        /// Deletes the existing entity.
        /// </summary>
        void Delete(Expression<Func<TEntity, bool>> where);
 
        /// <summary>
        /// Finds one entity based on provided criteria.
        /// </summary>
        TEntity FindOne(Expression<Func<TEntity, bool>> where = null);
 
        /// <summary>
        /// Finds one entity based on its Identifier.
        /// </summary>
        TEntity FindById(long id);
 
        /// <summary>
        /// Finds entities based on provided criteria.
        /// </summary>
        IQueryable<TEntity> FindAll(Expression<Func<TEntity, bool>> where = null);
 
        /// <summary>
        /// Finds other related entities based of type T for queries.
        /// </summary>
        IQueryable<T> Set<T>() where T : class;
 
        /// <summary>
        /// Save any changes to the TContext
        /// </summary>
        bool SaveChanges();
    }
}

Use an IoC like Ninject to inject the DbContext into the repo and then in turn use your IoC to inject the repo into service:

 
// Bootstrap or global.asax or whatever
 
// generic repository binding
Bind(typeof(IRepository<>)).To(typeof(Repository<,>));
// bind dbcontext to your entities extension
Bind(typeof(DbContext)).To(typeof(MyDbContextEntities));
 
// service layer constructor
public MyServiceConstructor(IRepository<Account, MyDbContextEntities> repository)
{
    _repository = repository;
}

Although the above does work very well and I do understand the need for the separation of concerns, but it does feel repetitious with the new “code first” approach. After all EF 4.3 with code first does follow a repository and unit of work pattern , as well as use POCOS.

~Troyka

Leave a comment

2 Comments.

  1. In the:

    public MyServiceConstructor(IRepository repository)
    {
    _repository = repository;
    }

    must be Repository instead IRepository

  2. Can you give me an example using this Repository and Unity for the DI container