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);
}
}
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.