1
\$\begingroup\$

I wanted to try something new in regards of design patterns. I have ended up with Unit Of Work with Repository and EF Core. So I just want to display my "real world" solution and maybe hear what you guys think..? Room for improvement or have I maybe overlooked a potential fatal exception? I used this guide with a few changes http://panictheorem.net/Blog/Repository-And-Unit-Of-Work

My project is a server/client where the server exposes a MVC WEB API, to be used by multiple winform clients on the same local network.

I have my service classes that handles each area of the system. In this example my MachineService is used. Each service class uses an abstract BaseClass that holds the UnitOfWork instance. Each of the service classes can use each other, but the instance of the UnitOfWork must be handed around. So the same instance of UnitOfWork is used for the whole transaction no matter how many service classes is in use.

Here is the code: Repository

public class Repository<T> : IRepository<T>, IDisposable where T : class
{
    protected CompleteDbContext dbContext;

    protected DbSet<T> dbSet;

    public Repository(CompleteDbContext context)
    {
        dbContext = context;
        dbSet = context.Set<T>();
    }

    public virtual IEnumerable<T> DataSet { get { return dbSet; } }

    public virtual void Create(T entity)
    {
        dbSet.Add(entity);
    }

    public virtual T GetById(Guid id)
    {
        return dbSet.Find(id);
    }

    public virtual void Update(T entity)
    {
        dbContext.Entry(entity).State = EntityState.Modified;
    }

    public virtual void Delete(T entity)
    {
        dbSet.Remove(entity);
    }

    public List<T> GetAllList()
    {
        return dbSet.ToList();
    }

    public virtual IQueryable<T> Query(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null)
    {
        IQueryable<T> query = dbSet;

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

        if (orderBy != null)
            query = orderBy(query);

        return query;
    }

    private bool disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!this.disposed)
        {
            if (disposing)
            {
                dbContext.Dispose();
            }
        }
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }
}

IRepository

public interface IRepository<T> : IDisposable where T : class
{
    IEnumerable<T> DataSet { get; }

    void Create(T entity);

    T GetById(Guid id);

    void Update(T entity);

    void Delete(T entity);

    List<T> GetAllList();

    IQueryable<T> Query(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null);
}

The base class for the service classes: BaseClass

public abstract class BaseService
{
    private UnitOfWork _unitOfWork;

    public UnitOfWork unitOfWork
    {
        get
        {
            if (this._unitOfWork == null)
            {
                _unitOfWork = new UnitOfWork();
            }
            return _unitOfWork;
        }
        set { _unitOfWork = value; }
    }

    public BaseService(UnitOfWork unitOfWork)
    {
        this.unitOfWork = unitOfWork;
    }

    public bool Commit()
    {
        try
        {
            unitOfWork.Commit();
            return true;
        }
        catch (Exception ex)
        {
            unitOfWork.Rollback();
            // log error
            return false;
        }
        finally
        {
            unitOfWork.Dispose();
        }
    }
}

And then the finally the MachineService that makes use of UnitOfWork.

    public class MachineService : BaseService, IMachineService
    {
        private MachineEventService _machineEvent;

        private MachineEventService machineEventService
        {
            get {
            if (_machineEvent == null)
                _machineEvent = new MachineEventService(unitOfWork);
            else
                return _machineEvent;
            }
            set { _machineEvent = value; }
        }

        public MachineService() : base(new UnitOfWork()) { }

        public MachineService(UnitOfWork unitOfWork) : base(unitOfWork) { }

        public Machine GetMachine(Guid machineId)
        {
            var machine = unitOfWork.MachineRepository.GetById(machineId);
            if (machine.CurrentEventId.HasValue)
            {
                machine.CurrentEvent =  machineEventService.GetEvent(machine.CurrentEventId.Value);
            }
            return machine;
        }
    }
\$\endgroup\$
  • 1
    \$\begingroup\$ Here it comes! See also this \$\endgroup\$ – Bruno Costa Jan 9 '17 at 15:11
  • \$\begingroup\$ The next person infected by the UoW/Repository virus ;-] \$\endgroup\$ – t3chb0t Jan 9 '17 at 19:26
  • \$\begingroup\$ Oh no what what?? Seems like i'm missing part of the story? :) \$\endgroup\$ – Christian Jan 9 '17 at 20:08
  • \$\begingroup\$ The thing is that EF's context is a UoW already. Just create a simple repository that uses the context internally a provides a bunch of queries that you can use in your application. There's no need to write another UoW. \$\endgroup\$ – t3chb0t Jan 10 '17 at 18:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.