Entity Framework 6, Repository pattern and Unit of Work

c# design-patterns entity-framework repository-pattern

Question

I am learning Entity Framework and some design patterns such repository pattern and unit of work. I wrote a program that uses these patterns. In this class I have one DbContext object and I always use this static DbContext. Throughout my application's lifetime, there is only one DbContext object. Am I doing right using this way, think if there are lots of users. Will be any problem about database connections.

UI code:

UnitOfWork uow = GetUnitOfWork(); //There is only one uow object
uow.EmployeeRepository.Insert(new Employee
{
    Name = name,
    Surname = surname
});

GetUnitOfWork code:

private static UnitOfWork _uow;
public static UnitOfWork GetUnitOfWork()
{
    return _uow ?? (_uow = new UnitOfWork());
}

UnitOfWork code:

public class UnitOfWork : IDisposable
{
    private static FollowerEntities _context;
    private DbContextTransaction _transaction;

    //repositories
    private EmployeeRepository _employeeRepository;


    public UnitOfWork()
    {
        _context = new FollowerEntities();
    }

    public EmployeeRepository EmployeeRepository
    {
        get { return _employeeRepository ?? (_employeeRepository = new EmployeeRepository(_context)); }
    }

    public void Save()
    {
        try
        {
            _transaction = _context.Database.BeginTransaction();
            _context.SaveChanges();
            _transaction.Commit();
        }
        catch
        {
            _transaction.Rollback();
            throw;
        }
    }

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

    private void Dispose(bool disposing)
    {
        if (disposing)
        {
            if (_context != null)
            {
                _context.Dispose();
                _context = null;
            }
        }
    }
}

Employee Repository

public class EmployeeRepository : GenericRepository<Employee>
{
    public EmployeeRepository(FollowerEntities entities)
        : base(entities)
    {

    }
}

Generic Repository

public class GenericRepository<T> where T : class
{
    private FollowerEntities _entities;


    private DbSet<T> table = null;

    public GenericRepository()
    {

    }

    public GenericRepository(FollowerEntities entities)
    {
        this._entities = entities;
        table = _entities.Set<T>();
    }

    public IEnumerable<T> SelectAll()
    {
        return table.ToList();
    }

    public T SelvectById(object id)
    {
        return table.Find(id);
    }

    public void Insert(T obj)
    {
        table.Add(obj);
    }

    public void Update(T obj)
    {
        table.Attach(obj);
        _entities.Entry(obj).State = EntityState.Modified;
    }

    public void Delete(object id)
    {
        T existing = table.Find(id);
        table.Remove(existing);
    }
}
1
2
11/17/2014 7:35:06 PM

Accepted Answer

private static UnitOfWork _uow;
public static UnitOfWork GetUnitOfWork()
{
    return _uow ?? (_uow = new UnitOfWork());
}

Although technically correct, this won't be as useful as you think. You limit the API to a single instance of the UoW. Considering shared scenarios like ASP.NET, this method won't probably be used as often as you think. I suggest removing it.

public UnitOfWork()
{
    _context = new FollowerEntities();
}

This unnecessarily couples the context lifetime to UoW lifetime. Instead, separate them:

public UnitOfWork( FollowerEntities context )
{
    _context = context;
}

This way, other means of lifetime management (IoC container possibly) could be used.

_transaction = _context.Database.BeginTransaction();
_context.SaveChanges();
_transaction.Commit();

Are you sure saves should always be wrapped in a transaction? What if another transaction exists on the same connection and you want to reuse it?

And the biggest issue - neither the UoW nor repositories are abstracted (with interfaces). This means that the client is still coupled to the sole implementation. You have just created a wrapped over Entity Framework but you can't benefit from it, for example, you can't switch to another implementation without rewriting it. I don't see any solid point in it, beside just excercising.

4
11/17/2014 7:47:25 PM


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