尝试在实体框架中实现UnitOfWork
我正在尝试了解工作单元模式。但是,我很难找到一个不太简单或不太复杂的示例。因此决定尝试根据我所读到的内容写一些自己的东西。我想知道我所做的事情是否可以接受。我正在尝试将各层解耦。我创建 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();
}
}
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();
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我认为您的工作单元实施很好并且应该有效。
这里还有其他可能的实现:
如果您将工作单元和存储库实现放置到单独的程序集中,那么应该就足够了。使用
ObjectContext
将是 EF DAL 程序集的内部实现,上层将不依赖于 EF 及其程序集。这可以通过引入 DALFactory 来进一步改进。 Factory 将负责实例化和处置
ObjectContext
以及创建 unitOfWork 和存储库。它将消除 UoW 和存储库之间的紧密耦合。我也在使用这个 实现将 UoW 和存储库的抽象工厂结合在一起,但自从我写了这个答案以来,我对它进行了一些修改。现在我的实现没有每个存储库的属性。相反,它使用通用方法返回所请求实体类型的存储库。存储库内部存储在字典中。但这个实现并不是很干净 UoW。
另一种流行的实现是:
I think your Unit of Work implementation is good and it should work.
Here you have other possible implementations:
If you place unit of work and repository implementations to separate assembly it should be enough. Working with
ObjectContext
will be internal implementation of EF DAL assembly and upper layers will have no dependency to EF and its assemblies.This can bu further improved by initroducing DALFactory. Factory will be responsible for instancing and disposing
ObjectContext
and creating unitOfWork and repositories. It will remove tight coupling between UoW and Repository.I'm also using this implementation which couples UoW and abstract factory for repositories but I have modified it little bit since I wrote that answer. Now my implementation doesn't have property for each repository. Instead it uses generic method which returns repository for requested entity type. Repositories are internally stored in dictionary. But this implementation is not very clean UoW.
Another popular implementation is: