I'm am trying to learn about the Unit Of Work pattern. However, I am having trouble finding an example that is not too simple or too complicated. So decided to try and write something of my own taking from what I have read. I was wondering if what I have done is acceptable. I am trying to have the layers decoupled. The reasons I created the DatabaseManager was to avoid sending the context to the other layers. In the end this will be the DAL for a MVC application with a middle layer (business)
Thanks for your input.
Code:
public interface IDatabaseFactory : IDisposable
{
ObjectContext Get();
}
public class DatabaseFactory : Disposable, IDatabaseFactory
{
private ObjectContext _dataContext;
#region IDatabaseFactory Members
public ObjectContext Get()
{
return _dataContext ?? (_dataContext = (new MyMemberDatabase()));
}
#endregion
protected override void DisposeCore()
{
if (_dataContext != null)
_dataContext.Dispose();
}
}
public static class DatabaseManager
{
private static readonly Dictionary<Guid, ObjectContext> ContextLists = new Dictionary<Guid, ObjectContext>();
public static ObjectContext GetContext(Guid id)
{
if (!ContextLists.ContainsKey(id))
{
Guid newContextID = id;
ContextLists.Add(newContextID, new DatabaseFactory().Get());
}
return ContextLists[id];
}
public static void RemoveContext(Guid id)
{
if (ContextLists[id] != null)
ContextLists.Remove(id);
}
}
public class Disposable : IDisposable
{
private bool _isDisposed;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~Disposable()
{
Dispose(false);
}
private void Dispose(bool disposing)
{
if (!_isDisposed && disposing)
{
DisposeCore();
}
_isDisposed = true;
}
protected virtual void DisposeCore()
{
}
}
public interface IUnitOfWork : IDisposable
{
Guid ContextID { get; }
void Commit();
}
public class UnitOfWork : IUnitOfWork
{
private readonly Guid _contextID;
public UnitOfWork()
{
_contextID = new Guid();
_contextID = Guid.NewGuid();
}
#region IUnitOfWork Members
public Guid ContextID
{
get { return _contextID; }
}
public void Commit()
{
DatabaseManager.GetContext(_contextID).SaveChanges();
}
public void Dispose()
{
DatabaseManager.RemoveContext(_contextID);
}
#endregion
}
public abstract class RepositoryBase<T> where T : class
{
private readonly IUnitOfWork _unitOfWork;
private ObjectContext _context;
private IObjectSet<T> _objectSet;
private ObjectContext Context
{
get { return _context ?? (_context = DatabaseManager.GetContext(_unitOfWork.ContextID)); }
}
protected IObjectSet<T> ObjectSet
{
get { return _objectSet ?? (_objectSet = Context.CreateObjectSet<T>()); }
}
protected RepositoryBase(IUnitOfWork unitOfWork)
{
_unitOfWork = unitOfWork;
}
}
class MemberRepository : RepositoryBase<Member>
{
public MemberRepository(IUnitOfWork unitOfWork) : base(unitOfWork)
{
}
public virtual void Add(Member entity)
{
ObjectSet.AddObject(entity);
}
public virtual void Delete(Member entity)
{
ObjectSet.DeleteObject(entity);
}
public virtual IEnumerable<Member> GetAll()
{
return ObjectSet.AsEnumerable();
}
}
EDIT: New Code
public interface IMemberRepository : IRepository
{
void Add(Member entity);
void Delete(Member entity);
IEnumerable<Member> GetAll();
}
public interface IRepository
{
IUnitOfWork UnitOfWork { get; }
}
public interface IUnitOfWork : IDisposable
{
void Commit();
}
public class DatabaseFactory : Disposable, IDisposable
{
private ObjectContext _dataContext;
public ObjectContext Get()
{
return _dataContext ?? (_dataContext = (new MyMemberDatabase()));
}
protected override void DisposeCore()
{
if (_dataContext != null)
_dataContext.Dispose();
}
}
public static class DatabaseManager
{
private static readonly Dictionary<Guid, ObjectContext> ContextLists = new Dictionary<Guid, ObjectContext>();
public static ObjectContext GetContext(Guid id)
{
if (!ContextLists.ContainsKey(id))
{
Guid newContextID = id;
ContextLists.Add(newContextID, new DatabaseFactory().Get());
}
return ContextLists[id];
}
public static void RemoveContext(Guid id)
{
if (ContextLists[id] != null)
ContextLists.Remove(id);
}
}
public class Disposable : IDisposable
{
private bool _isDisposed;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~Disposable()
{
Dispose(false);
}
private void Dispose(bool disposing)
{
if (!_isDisposed && disposing)
{
DisposeCore();
}
_isDisposed = true;
}
protected virtual void DisposeCore()
{
}
}
public class UnitOfWork : IUnitOfWork
{
private readonly Guid _contextID;
public UnitOfWork()
{
_contextID = new Guid();
_contextID = Guid.NewGuid();
}
#region IUnitOfWork Members
internal Guid ContextID
{
get { return _contextID; }
}
public void Commit()
{
DatabaseManager.GetContext(_contextID).SaveChanges();
}
public void Dispose()
{
DatabaseManager.RemoveContext(_contextID);
}
#endregion
}
public abstract class RepositoryBase<T> : IRepository where T : class
{
private readonly UnitOfWork _unitOfWork;
private ObjectContext _context;
private IObjectSet<T> _objectSet;
public IUnitOfWork UnitOfWork
{
get { return _unitOfWork; }
}
private ObjectContext Context
{
get { return _context ?? (_context = DatabaseManager.GetContext(_unitOfWork.ContextID)); }
}
protected IObjectSet<T> ObjectSet
{
get { return _objectSet ?? (_objectSet = Context.CreateObjectSet<T>()); }
}
protected RepositoryBase(IUnitOfWork unitOfWork)
{
_unitOfWork = (UnitOfWork)unitOfWork;
}
protected RepositoryBase()
{
_unitOfWork = new UnitOfWork();
}
}
public class MemberRepository : RepositoryBase<Member> ,IMemberRepository
{
public MemberRepository(IUnitOfWork unitOfWork) : base(unitOfWork)
{
}
public MemberRepository():base()
{
}
public virtual void Add(Member entity)
{
ObjectSet.AddObject(entity);
}
public virtual void Delete(Member entity)
{
ObjectSet.DeleteObject(entity);
}
public virtual IEnumerable<Member> GetAll()
{
return ObjectSet.AsEnumerable();
}
}