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

Do I need ninject when implementing DAL with generic repository and unit of work?

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

Problem

I am implementing generic repository and unit of work for the first time. I would be glad if someone can correct me if I am doing something wrong here.

This is how I communicate with my DAL from controller:

public class HomeController : Controller
    {
        private UnitOfWork unitOfWork = new UnitOfWork();

        public ActionResult Index()
        {
            var cities = unitOfWork.CityRepository.Get();


I instatiate unit of work in controller is this ok to it like this?

Unit of work contains all repositories so do I actually need to use ninject to inject repositories in controllers?

Suddenly when I finish this implementation I don't see use of injection as all repositories are in object that I instatiate in each controller?

This is my DAL classes:

```
public interface ICityRepository
{}
public class CityRepository : GenericRepository, ICityRepository
{}
public class GenericRepository where TEntity : class
{
internal MainContext context;
internal DbSet dbSet;

public GenericRepository(MainContext context)
{
this.context = context;
this.dbSet = context.Set();
}

public virtual IEnumerable Get(
Expression> filter = null,
Func, IOrderedQueryable> orderBy = null,
string includeProperties = "")
{
IQueryable query = dbSet;

if (filter != null)
{
query = query.Where(filter);
}

foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}

if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}
}

public virtual TEntity GetByID(object id)
{

Solution

Yes, you need a IOC container to maintain your instances. No, your Unit of Work should not create them.

With an IOC Container, you centralize the control over the objects and their lifetime. This is extremely powerful.

Never should you have an instantiation of unit of work, repositories, ... throughout your application code.

You're not the first person using UnitOfWork and IOC. There are tons of examples around on how to do this. I advise you to dig into IOC first (and not only how, but also why you use it, and what the benefits are), whether it's ninject or something else, that doesn't matter. I understand IOC being hard at first, but it's easy and useful once you master it.

Edit Example:

Below is an example on how I would implement this.
Please note, I do not use a separate unit of work, since my EF context is my unit of work.

The first issue you have is that you are not using interfaces; so my example is based on yours but I've added interfaces.

IMainContext interface:

public interface IMainContext
{
    IDbSet Set() where TEntity : class;
    DbEntityEntry Entry(TEntity entity) where TEntity : class;
    int SaveChanges();
}


IMainContext implementation for Entity Framework

public class MainContext : DbContext, IMainContext
{
     // your original MainContext code goes here
}


IGenericRepository

public interface IGenericRepository where TEntity : class
{
    IEnumerable Get(
        Expression> filter = null,
        Func, IOrderedQueryable> orderBy = null,
        string includeProperties = "");

    TEntity GetByID(object id);

    void Insert(TEntity entity);

    void Delete(object id);

    void Delete(TEntity entityToDelete);

    void Update(TEntity entityToUpdate);
}


GenericRepository

public class GenericRepository : IGenericRepository where TEntity : class
{
    private readonly IMainContext _context;
    private readonly IDbSet _dbSet;

    public GenericRepository(IMainContext context)
    {
        this._context = context;
        this._dbSet = context.Set();
    }

    public virtual IEnumerable Get(
        Expression> filter = null,
        Func, IOrderedQueryable> orderBy = null,
        string includeProperties = "")
    {
        IQueryable query = _dbSet;

        if (filter != null)
        {
            query = query.Where(filter);
        }

        foreach (var includeProperty in includeProperties.Split
            (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
        {
            query = query.Include(includeProperty);
        }

        if (orderBy != null)
        {
            return orderBy(query).ToList();
        }
        else
        {
            return query.ToList();
        }
    }

    public virtual TEntity GetByID(object id)
    {
        return _dbSet.Find(id);
    }

    public virtual void Insert(TEntity entity)
    {
        _dbSet.Add(entity);
    }

    public virtual void Delete(object id)
    {
        TEntity entityToDelete = _dbSet.Find(id);
        Delete(entityToDelete);
    }

    public virtual void Delete(TEntity entityToDelete)
    {
        if (_context.Entry(entityToDelete).State == EntityState.Detached)
        {
            _dbSet.Attach(entityToDelete);
        }
        _dbSet.Remove(entityToDelete);
    }

    public virtual void Update(TEntity entityToUpdate)
    {
        _dbSet.Attach(entityToUpdate);
        _context.Entry(entityToUpdate).State = EntityState.Modified;
    }
}


ICityRepository

public interface ICityRepository : IGenericRepository
{

}


CityRepository

public class CityRepository : GenericRepository, ICityRepository
{
    public CityRepository(IMainContext context) : base(context)
    {
    }
}

// I Used country as a second object, I have no idea what object you have besides City.
// I wanted two objects to demonstrate UOW usage
public class Country
{

}

public interface ICountryRepository : IGenericRepository
{

}

public class CountryRepository : GenericRepository, ICountryRepository
{
    public CountryRepository(IMainContext context)
        : base(context)
    {
    }
}


Now our controller constructor looks like this:

private readonly IMainContext _context;
private readonly ICityRepository _cityRepository;
private readonly ICountryRepository _countryRepository;

public HomeController(IMainContext context, ICityRepository cityRepository, ICountryRepository countryRepository)
{
    _context = context;
    _cityRepository = cityRepository;
    _countryRepository = countryRepository;
}


Now we can register our dependencies in MVC (global.asax)

```
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();

WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles)

Code Snippets

public interface IMainContext
{
    IDbSet<TEntity> Set<TEntity>() where TEntity : class;
    DbEntityEntry<TEntity> Entry<TEntity>(TEntity entity) where TEntity : class;
    int SaveChanges();
}
public class MainContext : DbContext, IMainContext
{
     // your original MainContext code goes here
}
public interface IGenericRepository<TEntity> where TEntity : class
{
    IEnumerable<TEntity> Get(
        Expression<Func<TEntity, bool>> filter = null,
        Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
        string includeProperties = "");

    TEntity GetByID(object id);

    void Insert(TEntity entity);

    void Delete(object id);

    void Delete(TEntity entityToDelete);

    void Update(TEntity entityToUpdate);
}
public class GenericRepository<TEntity> : IGenericRepository<TEntity> where TEntity : class
{
    private readonly IMainContext _context;
    private readonly IDbSet<TEntity> _dbSet;

    public GenericRepository(IMainContext context)
    {
        this._context = context;
        this._dbSet = context.Set<TEntity>();
    }

    public virtual IEnumerable<TEntity> Get(
        Expression<Func<TEntity, bool>> filter = null,
        Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null,
        string includeProperties = "")
    {
        IQueryable<TEntity> query = _dbSet;

        if (filter != null)
        {
            query = query.Where(filter);
        }

        foreach (var includeProperty in includeProperties.Split
            (new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
        {
            query = query.Include(includeProperty);
        }

        if (orderBy != null)
        {
            return orderBy(query).ToList();
        }
        else
        {
            return query.ToList();
        }
    }

    public virtual TEntity GetByID(object id)
    {
        return _dbSet.Find(id);
    }

    public virtual void Insert(TEntity entity)
    {
        _dbSet.Add(entity);
    }

    public virtual void Delete(object id)
    {
        TEntity entityToDelete = _dbSet.Find(id);
        Delete(entityToDelete);
    }

    public virtual void Delete(TEntity entityToDelete)
    {
        if (_context.Entry(entityToDelete).State == EntityState.Detached)
        {
            _dbSet.Attach(entityToDelete);
        }
        _dbSet.Remove(entityToDelete);
    }

    public virtual void Update(TEntity entityToUpdate)
    {
        _dbSet.Attach(entityToUpdate);
        _context.Entry(entityToUpdate).State = EntityState.Modified;
    }
}
public interface ICityRepository : IGenericRepository<City>
{

}

Context

StackExchange Code Review Q#57127, answer score: 8

Revisions (0)

No revisions yet.