2

First sorry if this was asked already but i cannot find an answer for this 'particular case'.

I've a Interface of Unit of Work:

public interface IUnitOfWork
{
    DbContext Context { get; set; }
    void Dispose();
    void Save();
}

And use a Generic Repository class:

public class GenericRepository<TEntity> where TEntity : class
    {

        private DbSet<TEntity> dbSet;

        private IUnitOfWork UnitOfWork { get; set; }
        private DbContext context { get { return UnitOfWork.Context; } }

        public GenericRepository(IUnitOfWork unitOfWork)
        {
            UnitOfWork = unitOfWork;
            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;
        }
    }

I don't want to do my logic in my MVC controler, so I added a businesslayer. My question is, where should I instantiate (and dispote) my IUnitOfWork, in my controler and pass it to my business layer? Example:

 public static class CircleLogic
    {
        public static void DeleteCircle(IUnitOfWork uow, int id)
        {
            try
            {
                var circleRep = new GenericRepository<Circle>(uow);

                var circle = circleRep.GetByID(id);
                 ......
                  circleRep.Delete(id);            

                uow.Save();

            }
            catch (Exception ex)
            {
                throw;
            }
        }
    }

I've seen this but I don't want to instantiate it in my business layer. What is the best approach?

Thanks!

Community
  • 1
  • 1
Tom
  • 944
  • 1
  • 14
  • 26
  • Hum, not sure why it would not? – Tom Oct 18 '12 at 08:08
  • IMO this is perfect case of abstraction bloat. You should rethink your layers and If you really need IUnitOfWork and generic repository if you are already using ORM. http://programmers.stackexchange.com/questions/164000/is-there-a-real-advantage-to-generic-repository – Euphoric Oct 18 '12 at 08:13
  • @Tom, You could inject the repository as well, if you had a constructor. – Morten Oct 18 '12 at 08:42
  • @Morten, thanks, that is one of my solution, create a non static class that would have 2 constructor.. i really don't need it as it s a simple implementaiton but i m trying to implrement stuff i never did just for learning sake – Tom Oct 18 '12 at 09:27
  • @euphoric, in my case it s totally useless to work with unitofwork as it's a simple website, but i saw on several tutorial, that it's good practice to be able to do TDD (which i won't), but it can be useful to understand – Tom Oct 18 '12 at 09:32

2 Answers2

3

I see no harm in passing it into your Business Layer like you have suggested. However, if you want to keep your Business Layer completely persistence ignorant I would suggest introducing an IRepository<T> interface and passing that in instead.

In terms of disposing of the objects, I would make both your IUnitOfWork/Repository classes implement IDisposable so you can make use of the using statement e.g.

public ActionResult DeleteCircle(int id)
{
    using (IUnitOfWork uow = new UnitOfWork())
    {
        using (IRepository<Circle> repo = new GenericRepository<Circle>(uow))
        {
            CircleLogic.DeleteCircle(repo, id);
        }
        uow.Save();
    }
}

...

public static class CircleLogic
{
    public static void DeleteCircle(IRepository<Circle> repo, int id)
    {
        var circle = repo.GetById(id);
        ...
        repo.Delete(id);
    }
}
James
  • 80,725
  • 18
  • 167
  • 237
  • Good points, thank you. I am still trying to decide if i want to completly remove the iunitofwork from my control and instantiate a kind of service with constructor. Just deciding if all of this is not overkill. Is it even good practice? Thanks again – Tom Oct 18 '12 at 09:36
  • @Tom "*Is it even good practise*" - It's good practise to introduce a base class in general if you find yourself repeating the same code - same applies to the repository pattern. If you only have a single repository then it may be overkill for now - but what if in the future you decide to add more? What seems like overkill now could actually make your life easier. Only you can decide whether or not your codebase needs a `GenericRepository` or `BaseRepository` to derive other from. – James Oct 18 '12 at 09:51
  • alright, thanks for your input, I will have a lot of repositories, as i already have like 10 tables for my project so it does make sense as you point out. I would think the most 'generic' solution then is make my CircleLogic with 2 constructor, (like mortem pointed out). I will merge both of your ideas :) Thanks! – Tom Oct 18 '12 at 10:42
1

Because your concrete UnitOfWork implementation would most likely live in your persistence layer, it'd be sensible to instantiate it in either the persistence layer or 1 layer above in the business layer. Your UI should have no knowledge of what technology you're using to persist your entities/data.

Adrian Thompson Phillips
  • 6,893
  • 6
  • 38
  • 69