使用IRepository和彼此的ASP.NET C#服务

时间:2014-07-28 09:37:03

标签: c# asp.net entity-framework

我的IRepository界面使用NinjectInRequestScope绑定。

存储库绑定是:

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

它确实“有效”,但这种方法有明显的垮台吗?

1 个答案:

答案 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();