这是一个围绕 DDD 进行存储库模式设计的良好工作单元吗?
我正在使用 UOW 和存储库模式构建一个 Web 应用程序。我对此有基本的了解,我想知道是否应该为项目中的所有表保留一个 UOW 实现,或者根据功能保留一个单独的 UOW 实现,例如:
public interface IHomeUOW
{
IGenericRepository<User> Users { get; }
IGenericRepository<TableA> Table_A { get; }
IGenericRepository<TableB> Table_B{ get; }
}
public interface IBusinessCaseUOW
{
IGenericRepository<TableA> Table_A { get; }
IGenericRepository<TableXYZ> Table_XYZ{ get; }
}
如您所见,TableA 在两个 Home UOW 中都可用以及 UOW 的特定业务案例。一个 UOW 部分实现如下:
public class UnitOfWork : IUnitOfWork
{
private readonly ObjectContext _context;
private UserRepository _userRepository;
public UnitOfWork(ObjectContext Context)
{
if (Context == null)
{
throw new ArgumentNullException("Context wasn't supplied");
}
_context = Context;
}
public IGenericRepository<User> Users
{
get
{
if (_userRepository == null)
{
_userRepository = new UserRepository(_context);
}
return _userRepository;
}
}
}
我的存储库将像这样
public interface IGenericRepository<T>
where T : class
{
//Fetch records
T GetSingleByRowIdentifier(int id);
T GetSingleByRowIdentifier(string id);
IQueryable<T> FindByFilter(Expression<Func<T, bool>> filter);
// CRUD Ops
void AddRow(T entity);
void UpdateRow(T entity);
void DeleteRow(T entity);
}
public abstract class GenericRepository<T> : IGenericRepository<T>
where T : class
{
protected IObjectSet<T> _objectSet;
protected ObjectContext _context;
public GenericRepository(ObjectContext Context)
{
_objectSet = Context.CreateObjectSet<T>();
_context = Context;
}
//Fetch Data
public abstract T GetSingleByRowIdentifier(int id);
public abstract T GetSingleByRowIdentifier(string id);
public IQueryable<T> FindByFilter(Expression<Func<T, bool>> filter)
{
//
}
//CRUD Operations implemented
}
public class UserRepository : GenericRepository<User>
{
public UserRepository(ObjectContext Context)
: base(Context)
{
}
public override User GetSingleByRowIdentifier(int id)
{
//implementation
}
public override User GetSingleByRowIdentifier(string username)
{
//implementation
}
}
你觉得怎么样?如果这不是 DDD 的 UOW 和存储库模式的正确实现,它是否会因为编写一堆代码来抽象对 EF 表的调用而失败?
谢谢你的时间..
I am building a web app with using UOW and Repository pattern. I have a basic understanding of the same and I wanted to know if I should keep one UOW implementation for all the tables in my project or keep a separate one as per functionality like for eg:
public interface IHomeUOW
{
IGenericRepository<User> Users { get; }
IGenericRepository<TableA> Table_A { get; }
IGenericRepository<TableB> Table_B{ get; }
}
public interface IBusinessCaseUOW
{
IGenericRepository<TableA> Table_A { get; }
IGenericRepository<TableXYZ> Table_XYZ{ get; }
}
As you can see TableA is available in both Home UOW as well as a particular business case UOW. One UOW partially implemented as below:
public class UnitOfWork : IUnitOfWork
{
private readonly ObjectContext _context;
private UserRepository _userRepository;
public UnitOfWork(ObjectContext Context)
{
if (Context == null)
{
throw new ArgumentNullException("Context wasn't supplied");
}
_context = Context;
}
public IGenericRepository<User> Users
{
get
{
if (_userRepository == null)
{
_userRepository = new UserRepository(_context);
}
return _userRepository;
}
}
}
My repositories will be like so
public interface IGenericRepository<T>
where T : class
{
//Fetch records
T GetSingleByRowIdentifier(int id);
T GetSingleByRowIdentifier(string id);
IQueryable<T> FindByFilter(Expression<Func<T, bool>> filter);
// CRUD Ops
void AddRow(T entity);
void UpdateRow(T entity);
void DeleteRow(T entity);
}
public abstract class GenericRepository<T> : IGenericRepository<T>
where T : class
{
protected IObjectSet<T> _objectSet;
protected ObjectContext _context;
public GenericRepository(ObjectContext Context)
{
_objectSet = Context.CreateObjectSet<T>();
_context = Context;
}
//Fetch Data
public abstract T GetSingleByRowIdentifier(int id);
public abstract T GetSingleByRowIdentifier(string id);
public IQueryable<T> FindByFilter(Expression<Func<T, bool>> filter)
{
//
}
//CRUD Operations implemented
}
public class UserRepository : GenericRepository<User>
{
public UserRepository(ObjectContext Context)
: base(Context)
{
}
public override User GetSingleByRowIdentifier(int id)
{
//implementation
}
public override User GetSingleByRowIdentifier(string username)
{
//implementation
}
}
What do you think? If this is not the correct implementation of UOW and Repository pattern for DDD, will it fail as just a bunch of code written to abstract the call to the EF tables?
Thanks for your time..
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我对通用存储库过敏。每次我使用它时,我都必须采取打破开放/封闭原则的变通办法。
我建议您切换到根聚合特定存储库并在其中使用您的 OR/M。
至于工作单位。 EF 和 nhibernate 确实已经实现了该模式。只需创建一个接口,例如:
处置而不保存=回滚。
nhibernate 实现看起来像(快速编写,未测试):
使用 IoC 容器使其变得非常简单。只需在其中注册实现即可。
在 ASP.NET MVC 中获得事务支持的我最喜欢的解决方案是创建一个名为
TransactionalAttribute
的自定义ActionFilter
并让它处理 UnitOfWork 实现:我刚刚将答案转换为更详细的博客文章:http://blog.gauffin.org/2012/02/repositories-unit-of-work-and-asp-net-mvc/
I'm allergic to generic repositories. Each time I've used one I've had to do workarounds which breaks open/closed principle.
I recommend that you switch to root aggregate specific repositories and use your OR/M in them.
As for unit of work. EF and nhibernate do already implement the pattern. Simply create an interface like:
Disposing without saving = Rollback.
A nhibernate implementation would look like (quick writeup, not tested):
Using an IoC container makes it really easy. Just register the implementation in it.
My favorite solution to get transaction support in ASP.NET MVC is to create a custom
ActionFilter
named something likeTransactionalAttribute
and let it handle the UnitOfWork implementation:I just converted the answer into a more detailed blog post: http://blog.gauffin.org/2012/02/repositories-unit-of-work-and-asp-net-mvc/
我认为这是错误的。
UnitOfWork 是事务(简单来说)。它至少应该包含一个方法 Complete(Commit)。
如果您使用EntityFramework,则包装ObjectContext;如果您使用纯ADO .NET,则包装TransactionScope;如果使用NHibernate ISession,等等。
这是我的UOF:
I think this is wrong.
UnitOfWork is Transaction (in simple words). It least it should contain one method Complete(Commit).
If you work with EntityFramework you wrap ObjectContext, if you work with pure ADO .NET you wrap TransactionScope, if with NHibernate ISession, etc.
Here is my UOF: