0

我目前正在编写一个 Windows 服务,它使用实体框架(DbContext)连接到现有服务层,并使用 Ninject 注入 Respositories 和 DbContext 实例。这几乎与一个警告一起工作 - 每次线程运行时我都想要一个全新的 DbContext 实例,而目前我在整个线程生命周期中都得到相同的实例。

我的绑定看起来像这样:

Bind<IDbContext>().To<EnterpriseDbContext>().InThreadScope();
Bind<IUserRepository>().To<UserRepository>().InThreadScope();
// And other repositories

我的线程代码如下所示:

[Inject]
public IDbContext DbContext { get; set; }

// Execute indefinitely (or until we've stopped)
while (true && !isStopping)
{
   try
   {
      // Do work.

      // Save any changes.
      DbContext.SaveAnyChanges();
    } 
    catch (Exception ex)
    {
       // Handle exception
       HandleException(ex);
    }

    // Sleep
    Thread.Sleep(sleepInterval);
 }

现在我知道我可以将范围更改为 InTransientScope() 等 - 但是我对 Ninject 还是很陌生,而且我不确定如何最好地组织代码以每次使用新的 DbContext 实例。

有没有人做过类似的事情?在 Web 应用程序中,我们有 InRequestScope() 可以完美运行 - 但我不确定如何在 Windows 服务中使用 DbContext 的最佳方法。

4

1 回答 1

3

看这里的答案

在 Ninject2 中,您可以通过以下方式执行此操作:

Bind<IService>().To<ServiceImpl>().InScope(ctx => ...);

传递给的回调返回的对象InScope()成为范围内激活的实例的“拥有”对象。这有两个含义:

  1. 如果回调为多个激活返回相同的对象,Ninject 将重新使用第一次激活的实例。

  2. 当从回调返回的对象被垃圾回收时,Ninject 将停用(“拆除”、调用 Dispose() 等)与该对象关联的任何实例。

例如,用于的回调InRequestScope()是:

ctx => HttpContext.Current

由于在每个 Web 请求上HttpContext.Current设置为一个新实例,HttpContext因此每个请求只会激活一个服务实例,当请求结束并且HttpContext(最终)收集时,这些实例将被停用。

INotifyWhenDisposed如果您想确定性地停用“拥有”实例,则回调返回的对象也可以实现Ninject 的接口。如果作用域对象实现了这个接口,当它被 Dispose()'d 时,它拥有的任何实例都将立即被停用。

于 2013-09-06T11:23:14.057 回答