我的IRepository
界面使用Ninject
和InRequestScope
绑定。
存储库绑定是:
kernel.Bind<IRepository>().To<DefaultRepository>().InRequestScope().WithConstructorArgument("dbContext", dbContext => kernel.Get<DefaultContext>());
如果我有一个以相同方式绑定的服务IAccountService
。
具体实施:
public class AccountService : IAccountService
{
IRepository _repository;
public AccountService(IRepository repository) { _repository = repository; }
}
如果我现在创建另一个以相同方式绑定的服务IBlogService
。
具体实施:
public class BlogService : IBlogService
{
IRepository _repository;
IAccountService _accountService;
public AccountService(IRepository repository, IAccountService accountService)
{
_repository = repository;
_accountService = accountService;
}
}
这两项服务都要求IRepository
他们是获得相同的实例,还是他们要求两个完全不同的孤立DbContext
?
它确实“有效”,但这种方法有明显的垮台吗?
答案 0 :(得分:2)
由于您使用.InRequestScope()
,所有服务在您的请求期间都会获得DefaultRepository
的相同实例。因此,当有新请求进入时,会创建DefaultRepository
的新实例。
如果你的IRepository
接口实现了IDisposable
,Ninject会在需要时处理它。
我认为没有任何垮台,因为在网络应用程序中,DbContext
的生命周期应该是每次请求(除非你有充分的理由不遵循这种方法)。
修改强>
您还可以按请求模式实现事务,因此如果在一个存储库中保存成功,则可以避免不一致,但在另一个存储库中保存会失败。这样,如果在请求期间出现任何问题,您可以回滚所有更改。
不是说你应该实现这个,只是想让你知道它是可能的。这是一个非常基本的示例,您应该在何时创建事务时进行一些额外的检查(例如,仅在http POSTS上),并且您可能希望将其委托给单独的类,以便您的Global.asax不会混乱所有这些resposiblilites。另外要提到的是,只有在你的DbContext注入了.InRequestScope()时才会有效,所以你的请求会使用相同的上下文。
它的工作原理如下:
在您的Global.asax Application_BeginRequest()方法中,您应该像这样初始化您的交易:
var transaction = _context.Database.BeginTransaction(IsolationLevel.ReadCommitted);
_httpContext.Items["_Transaction"] = transaction;
在Global.asax Application_Error()方法中,您可以像这样设置错误标志
_httpContext.Items["_Error"] = true;
最后在您的Global.asax Application_EndRequest()中,如果没有错误,您可以提交所有内容,或者回滚:
var transaction = (DbContextTransaction)_httpContext.Items["_Transaction"];
if (_httpContext.Items["_Error"] != null)
transaction.Rollback();
else
transaction.Commit();