我目前的观点是存储库应该包含特定于实体的修改方法,如添加,删除等.而UnitOfWork应该只包含与它相关的方法,如Commit(也称为SaveChanges,SubmitChanges)和Rollback(也称为作为ClearChanges).但Martin Fowler在他关于UnitOfWork的文章中建议将所有修改方法添加到UnitOfWork中.
那么现在哪种方式更好,在EF和NHibernate的世界?
更新. 我应该注意,即使采用我更好的方法,最后通过存储库的所有修改都会进入内置于EF Context或NHibernate Session的UnitOfWork.而我的UnitOfWork更像是UnitOfWorkManager(它管理内部ORM UnitOfWork).
我已经实现了工作单元/存储库模式,如此处所述,但我还使用 autofac 和构造函数注入,因此我注册了 UnitOfWork 和 DbContext (PsyProfContext) 类,如下所示:
builder.Register(context => new PsyProfContext()).InstancePerHttpRequest();
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerHttpRequest();
Run Code Online (Sandbox Code Playgroud)
一切都很好!
除了一件事:我还使用企业库日志记录块,并且我已经实现了 CustomTraceListener,它使用实体框架将日志条目写入数据库。
我的控制器看起来像这样(它是空的,因为目前我只是尝试验证所有东西(IoC、日志记录、实体框架)是否正常工作):
public class HomeController : Controller
{
private readonly UnitOfWork unitOfWork;
public HomeController(IUnitOfWork unitOfWork)
{
this.unitOfWork = (UnitOfWork) unitOfWork;
}
//
// GET: /Home/
public ActionResult Index()
{
throw new HttpException();
return View();
}
protected override void Dispose(bool disposing)
{
unitOfWork.Dispose();
base.Dispose(disposing);
}
}
Run Code Online (Sandbox Code Playgroud)
在 CustomTraceListener 类的 Write 方法中,我尝试解析 UnitOfWork:
DependencyResolver.Current.GetService<IUnitOfWork>() as UnitOfWork;
Run Code Online (Sandbox Code Playgroud)
但我得到一个已经被处置的实例!所以我设置了一些断点,发现控制器的Dispose方法是在CustomTraceListener类的Write方法之前调用的,所以最后我除了直接使用DbContext(PsyProfContext)之外没有找到其他解决方案:
public override void Write(object o)
{ …Run Code Online (Sandbox Code Playgroud) enterprise-library unit-of-work autofac repository-pattern asp.net-mvc-4
我一直在涂鸦和阅读,只是想确保我采取的方法是正确的.我正在使用MVC5和EF,实现存储库和工作单元模式.
EntityModel -> <- SomeRepository
SomeRepository -> <- SomeController
SomeController -> SomeViewModel
SomeViewModel -> SomeView
SomeView -> SomeController
SomeController -> <- SomeRepository
etc ..
Run Code Online (Sandbox Code Playgroud)
在控制器中,我计划使用类似AutoMapper的东西将ViewModel映射到EntityModel(反之亦然),然后可以将其传递到我的存储库/视图.
此外,通过这种方法,我不能100%确定我的业务逻辑应该去哪里.例如,如果我有一个产品的EntityModel并且我想添加一个GetAssociatedProducts方法,这是否会违反EntityModel或者是否应该引入另一个层,因此EntityModel只是一个简单的数据库映射类?
ViewModel应该包含任何逻辑吗?即创建一个Dictionary根据EntityModel的值填充视图的下拉列表?
我试图避免与刚开始编码相关的问题,而不考虑这个问题的原因是什么.
注意:我也在实现IoC,Autofac但我不认为这是相关的(以防万一).
我正在使用Repository和UoW模式.我的服务看起来像这样:
public class MyService : IService
{
private readonly IUnitOfWork<MyContext> unitOfWork;
private readonly IMyRepository myRepository;
public MyService(IUnitOfWork<MyContext> unitOfWork, IMyRepository myRepository)
{
this.unitOfWork = unitOfWork;
this.myRepository = myRepository;
}
//Methods...
}
Run Code Online (Sandbox Code Playgroud)
在服务中,我需要使用其他实体(例如检查权限等).
是否建议在服务中使用相关存储库或直接使用服务?
此外,对于每个用户,我们对每个CRUD操作都有权限(布尔值).这些权限存储在数据库中.
是否应在控制器级别或服务级别检查权限?
我有一个有趣的用例,其中某些异常类型意味着"此消息不再有效且应该被忽略"但是此代码没有任何意识,Bus以便调用Bus.DoNotContinueDispatchingCurrentMessageToHandlers().
我讨厌像每个消息处理程序中都需要的try/catch块这样的样板代码.所以我开始实现一个UnitOfWork来处理和吞下异常,但我找不到告诉框架的方法"是的,这个代码生成了一个异常,但忘记了这一点,只是完成了事务."
Bus.DoNotContinueDispatchingCurrentMessageToHandlers()不起作用.我尝试过ITransport注入和调用,AbortHandlingCurrentMessage()但这导致整个宇宙爆炸.即使单步执行源代码,我似乎也不知所措.
请注意,很可能这是一个可怕的想法,因为假设实际上存在异常情况时没有异常将导致事务提交,从而导致谁知道有多少不良的未知副作用.因此,最好有一个方法仍然回滚事务但丢弃该消息.但我会对潜在的"是的我知道我在做什么,提交交易而不管异常"选项感兴趣.
unit-of-work ×5
.net ×1
asp.net-mvc ×1
autofac ×1
c# ×1
nhibernate ×1
nservicebus ×1
repository ×1