我正在努力了解工作单元模式。但是,我很难找到一个不太简单或太复杂的例子。所以我决定尝试用自己所读的东西来写一些自己的东西。我想知道我所做的事情是否可以接受。我试图让图层分离。我创建DatabaseManager的原因是为了避免将上下文发送到其他层。最后,这将是具有中间层(业务)的MVC应用程序的DAL
感谢您的意见。
代码:
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();
}
}
编辑:新代码
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();
}
}
答案 0 :(得分:2)
我认为您的工作单位实施情况良好,应该有效。
这里有其他可能的实现:
// Interface used by upper layer
public interface IUnitOfWork : IDisposable
{
void Commit();
}
// EF dependent unit of work
public class EFUnitOfWork : IUnitOfWork
{
private readonly ObjectContext _context = new ObjectContext(...);
internal ObjectContext Context
{
get { return _context; }
}
...
}
// EF dependent repository - upper layer uses interface
public abstract class EFRepositoryBase<T> : IRepository<T> where T : class
{
private readonly ObjectContext _context;
private IObjectSet<T> _objectSet;
// yes unit of work and repository is tightly coupled because they both have
// to work with EF
public EFRepositoryBase(EFUnitOfWork unitOfWork)
{
_context = unitOfWork.Context;
}
...
}
如果将工作单元和存储库实现放在单独的程序集中,那就足够了。使用ObjectContext
将是EF DAL程序集的内部实现,而上层将不依赖于EF及其程序集。
通过初始化DALFactory可以进一步改善这一点。 Factory将负责实例化和处置ObjectContext
以及创建unitOfWork和存储库。它将消除UoW和Repository之间的紧密耦合。
我也在使用this实现,它将UoW和抽象工厂耦合为存储库,但是自从我写完这个答案以来,我对它进行了一些修改。现在我的实现没有每个存储库的属性。相反,它使用泛型方法返回所请求实体类型的存储库。存储库内部存储在字典中。但是这个实现并不是很干净UoW。
另一个流行的实现是:
// Interface used by upper layer
public interface IUnitOfWork : IDisposable
{
void SaveChanges();
}
public class UnitOfWork : ObjectContext, IUnitOfWork
{
}